Jeg kan give dig et svar og et gæt:
Først bruger jeg en erklæret tabelvariabel til at mock up dit scenarie:
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>');
--Denne forespørgsel vil læse XML med en cast ud af en sub-select . Du kan bruge en CTE
i stedet, men dette bør kun være syntaktisk sukker...
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);
--Den anden del bruger en tabel til at skrive i den indtastede XML og læse derfra:
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);
Hvorfor er /text()
hurtigere end uden /text()
?
Hvis du ser på mit eksempel, er indholdet af et element alt fra åbningsmærket ned til det afsluttende mærke . text()
af et element er den flydende tekst mellem disse tags. Du kan se dette i resultaterne af valget ovenfor. text()
er en separat lagret del i en træstruktur faktisk (læs næste afsnit). At hente det er en et-trins-handling . Ellers skal en kompleks struktur analyseres for at finde alt mellem åbningstagget og dets tilsvarende afsluttende tag - også selvom der ikke er andet end text()
.
Hvorfor skal jeg gemme XML i den passende type?
XML er ikke bare tekst med nogle fjollede ekstrategn! Det er et dokument med en kompleks struktur. XML'et gemmes ikke som den tekst, du ser . XML er gemt i en træstruktur. Når du kaster en streng, som repræsenterer en XML, ind i en rigtig XML, skal dette meget dyre arbejde udføres. Når XML præsenteres for dig (eller et hvilket som helst andet output), er den repræsenterende streng (gen)bygget fra bunden.
Hvorfor er den præcastede tilgang hurtigere
Dette er at gætte...
I mit eksempel er begge tilgange ret lige og fører til (næsten) den samme eksekveringsplan.
SQL Server vil ikke arbejde ned alt, som du kunne forvente dette. Dette er ikke et proceduresystem, hvor du angiver gør dette, end gør dette og efter gør dette! . Du fortæller motoren, hvad du vil have, og motoren bestemmer, hvordan den bedst gør det. Og motoren er ret god med dette!
Før udførelsen starter, forsøger motoren at estimere omkostningerne ved tilgange. CONVERT
(eller CAST
) er en ret billig operation. Det kunne være, at motoren beslutter sig for at arbejde ned på listen over dine opkald og lave castet for hvert enkelt behov igen og igen, fordi den mener, at dette er billigere end den dyre oprettelse af en afledt tabel...