Caramba. Este foi um tópico realmente útil para descobrir.
Ainda achei algumas dessas sugestões confusas. Sempre que usei value
com [1]
na string, ele recuperaria apenas o primeiro valor. E algumas sugestões recomendaram usar o cross apply
que (em meus testes) apenas trouxe de volta muitos dados.
Portanto, aqui está meu exemplo simples de como você criaria um xml
objeto e, em seguida, leria seus valores em uma tabela.
DECLARE @str nvarchar(2000)
SET @str = ''
SET @str = @str + '<users>'
SET @str = @str + ' <user>'
SET @str = @str + ' <firstName>Mike</firstName>'
SET @str = @str + ' <lastName>Gledhill</lastName>'
SET @str = @str + ' <age>31</age>'
SET @str = @str + ' </user>'
SET @str = @str + ' <user>'
SET @str = @str + ' <firstName>Mark</firstName>'
SET @str = @str + ' <lastName>Stevens</lastName>'
SET @str = @str + ' <age>42</age>'
SET @str = @str + ' </user>'
SET @str = @str + ' <user>'
SET @str = @str + ' <firstName>Sarah</firstName>'
SET @str = @str + ' <lastName>Brown</lastName>'
SET @str = @str + ' <age>23</age>'
SET @str = @str + ' </user>'
SET @str = @str + '</users>'
DECLARE @xml xml
SELECT @xml = CAST(CAST(@str AS VARBINARY(MAX)) AS XML)
-- Iterate through each of the "users\user" records in our XML
SELECT
x.Rec.query('./firstName').value('.', 'nvarchar(2000)') AS 'FirstName',
x.Rec.query('./lastName').value('.', 'nvarchar(2000)') AS 'LastName',
x.Rec.query('./age').value('.', 'int') AS 'Age'
FROM @xml.nodes('/users/user') as x(Rec)
E aqui está o resultado:
É uma sintaxe bizarra, mas com um exemplo decente, é fácil de adicionar às suas próprias funções do SQL Server.
Falando nisso, aqui está a resposta correta para essa pergunta.
Supondo que você tenha seus dados xml em uma @xml
variável do tipo xml
(conforme demonstrado no meu exemplo acima), veja como você retornaria as três linhas de dados do xml citado na pergunta:
SELECT
x.Rec.query('./firstName').value('.', 'nvarchar(2000)') AS 'FirstName',
x.Rec.query('./lastName').value('.', 'nvarchar(2000)') AS 'LastName'
FROM @xml.nodes('/person') as x(Rec)