Мога да ви дам един отговор и едно предположение:
Първо използвам декларирана таблична променлива за мокет вашият сценарий:
DECLARE @tbl TABLE(s NVARCHAR(MAX));
INSERT INTO @tbl VALUES
(N'<root>
<SomeElement>This is first text of element1
<InnerElement>This is text of inner element1</InnerElement>
This is second text of element1
</SomeElement>
<SomeElement>This is first text of element2
<InnerElement>This is text of inner element2</InnerElement>
This is second text of element2
</SomeElement>
</root>')
,(N'<root>
<SomeElement>This is first text of elementA
<InnerElement>This is text of inner elementA</InnerElement>
This is second text of elementA
</SomeElement>
<SomeElement>This is first text of elementB
<InnerElement>This is text of inner elementB</InnerElement>
This is second text of elementB
</SomeElement>
</root>');
--Тази заявка ще прочете XML с изхвърляне на под-селекция . Може да използвате CTE
вместо това, но това трябва да е само синтактична захар...
SELECT se.value(N'(.)[1]','nvarchar(max)') SomeElementsContent
,se.value(N'(InnerElement)[1]','nvarchar(max)') InnerElementsContent
,se.value(N'(./text())[1]','nvarchar(max)') ElementsFirstText
,se.value(N'(./text())[2]','nvarchar(max)') ElementsSecondText
FROM (SELECT CAST(s AS XML) FROM @tbl) AS tbl(TheXml)
CROSS APPLY TheXml.nodes(N'/root/SomeElement') AS A(se);
--Втората част използва таблица за запис във въведения XML и четене от там:
DECLARE @tbl2 TABLE(x XML)
INSERT INTO @tbl2
SELECT CAST(s AS XML) FROM @tbl;
SELECT se.value(N'(.)[1]','nvarchar(max)') SomeElementsContent
,se.value(N'(InnerElement)[1]','nvarchar(max)') InnerElementsContent
,se.value(N'(./text())[1]','nvarchar(max)') ElementsFirstText
,se.value(N'(./text())[2]','nvarchar(max)') ElementsSecondText
FROM @tbl2 t2
CROSS APPLY t2.x.nodes(N'/root/SomeElement') AS A(se);
Защо е /text()
по-бързо, отколкото без /text()
?
Ако погледнете моя пример, съдържанието на елемент е всичко от началния таг надолу до затварящия таг . text()
на елемент е плаващият текст между тези тагове. Можете да видите това в резултатите от избора по-горе. text()
е еднаотделно съхранявана част в дървовидна структура всъщност (прочетете следващия раздел). Извличането му е действие в една стъпка . В противен случай трябва да се анализира сложна структура, за да се намери всичко между началния таг и съответния му затварящ маркер - дори ако няма нищо друго освен text()
.
Защо трябва да съхранявам XML в подходящия тип?
XML не е просто текст с някои глупави допълнителни знаци! Това е документ със сложна структура. XML не се съхранява като текста, който виждате . XML се съхранява в дървовидна структура. Всеки път, когато прехвърляте низ, който представлява XML, в истински XML, тази много скъпа работа трябва да се свърши. Когато ви бъде представен XML (или друг изход), представляващият низ се (пре)изгражда от нулата.
Защо предварително изготвеният подход е по-бърз
Това е предположение...
В моя пример и двата подхода са доста равни и водят до (почти) един и същ план за изпълнение.
SQL Server няма да работи надолу по начина, по който може да очаквате това. Това не е процедурна система, в която казвате направете това, след това направете това и след това направете това! . Вие казвате на двигателя какво искате и двигателят решава как да направи това най-добре. И двигателят е доста добър с това!
Преди да започне изпълнението, двигателят се опитва да оцени разходите за подходи. CONVERT
(или CAST
) е доста евтина операция. Възможно е двигателят да реши да изработи списъка с вашите обаждания и да прави прехвърляне за всяка отделна нужда отново и отново, защото смята, че това е по-евтино от скъпото създаване на производна таблица...