Posso dar-lhe uma resposta e um palpite:
Primeiro eu uso uma variável de tabela declarada para simular seu cenário:
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>');
--Esta consulta lerá o XML com uma conversão de uma sub-seleção . Você pode usar um
CTE
em vez disso, mas isso deve ser apenas açúcar sintático ... 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);
--A segunda parte usa uma tabela para escrever no XML digitado e ler a partir daí:
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);
Por que /text()
mais rápido do que sem /text()
?
Se você observar meu exemplo, o conteúdo de um elemento é tudo da tag de abertura até a tag de fechamento . O
text()
de um elemento é o texto flutuante entre essas etiquetas. Você pode ver isso nos resultados do select acima. O text()
é uma parte armazenada separadamente em uma estrutura de árvore na verdade (leia a próxima seção). Para buscá-lo, é uma ação de uma etapa . Caso contrário, uma estrutura complexa deve ser analisada para encontrar tudo entre a tag de abertura e sua tag de fechamento correspondente - mesmo que não haja nada além do text()
. Por que devo armazenar XML no tipo apropriado?
XML não é apenas texto com alguns caracteres extras bobos! É um documento com uma estrutura complexa. O XML não é armazenado como o texto que você vê . XML é armazenado em uma estrutura de árvore. Sempre que você converte uma string, que representa um XML, em um XML real, esse trabalho muito caro deve ser feito. Quando o XML é apresentado a você (ou qualquer outra saída), a string de representação é (re)construída do zero.
Por que a abordagem pré-fabricada é mais rápida
Isso é suposição...
No meu exemplo, ambas as abordagens são bastante iguais e levam a (quase) o mesmo plano de execução.
O SQL Server não funcionará da maneira que você espera. Este não é um sistema de procedimentos onde você declara faça isso, depois faça isso e depois faça isso! . Você diz ao motor o que deseja, e o motor decide como fazer isso melhor. E o mecanismo é muito bom com isso!
Antes de iniciar a execução, o mecanismo tenta estimar os custos das abordagens.
CONVERT
(ou CAST
) é uma operação bastante barata. Pode ser que o mecanismo decida trabalhar na lista de suas chamadas e fazer o elenco para cada necessidade única vez após vez, porque acha que isso é mais barato do que a criação cara de uma tabela derivada ...