Jag kan ge dig ett svar och en gissning:
Först använder jag en deklarerad tabellvariabel för att mock up ditt scenario:
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>');
--Den här frågan läser XML med en cast ut ur en sub-select . Du kan använda en CTE
istället, men det här ska bara vara syntaktiskt socker...
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 andra delen använder en tabell för att skriva in den inskrivna XML-filen och läsa därifrån:
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);
Varför är /text()
snabbare än utan /text()
?
Om du tittar på mitt exempel är innehållet i ett element allt från den inledande taggen ner till den avslutande taggen . text()
av ett element är den svävande texten mellan dessa taggar. Du kan se detta i resultaten av urvalet ovan. text()
är en separat lagrad del i en trädstruktur faktiskt (läs nästa avsnitt). Att hämta det är en en-stegs-åtgärd . Annars måste en komplex struktur analyseras för att hitta allt mellan öppningstaggen och dess motsvarande avslutande tagg - även om det inte finns något annat än text()
.
Varför ska jag lagra XML i lämplig typ?
XML är inte bara text med några fåniga extratecken! Det är ett dokument med en komplex struktur. XML lagras inte som texten du ser . XML lagras i en trädstruktur. Närhelst du gjuter en sträng, som representerar en XML, till en riktig XML, måste detta mycket dyra arbete utföras. När XML presenteras för dig (eller någon annan utdata) är den representerande strängen (om)byggd från grunden.
Varför är det förgjutna tillvägagångssättet snabbare
Det här är att gissa...
I mitt exempel är båda tillvägagångssätten ganska lika och leder till (nästan) samma exekveringsplan.
SQL Server kommer inte att fungera ner allt som du kan förvänta dig. Detta är inte ett procedursystem där du säger att gör detta, än gör detta och gör det här efteråt! . Du berättar för motorn vad du vill ha, och motorn bestämmer hur man gör detta bäst. Och motorn är ganska bra med detta!
Innan utförandet startar försöker motorn uppskatta kostnaderna för tillvägagångssätt. CONVERT
(eller CAST
) är en ganska billig operation. Det kan vara så att motorn bestämmer sig för att arbeta ner listan över dina samtal och göra casten för varje enskilt behov om och om igen, eftersom den tror att detta är billigare än det dyra skapandet av en härledd tabell...