Cholera. To był naprawdę przydatny wątek do odkrycia.
Nadal uważam, że niektóre z tych sugestii są mylące. Za każdym razem, gdy użyłem znaku value
with [1]
w ciągu, pobierałbym tylko pierwszą wartość. I niektóre sugestie zalecały użycie, cross apply
które (w moich testach) po prostu przywróciło zbyt dużo danych.
Oto mój prosty przykład, jak utworzyć xml
obiekt, a następnie odczytać jego wartości w tabeli.
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)
A oto wynik:
Jest to dziwaczna składnia, ale z przyzwoitym przykładem wystarczy dodać do własnych funkcji SQL Server.
A skoro o tym mowa, oto poprawna odpowiedź na to pytanie.
Zakładając, że masz swoje dane xml w @xml
zmiennej typu xml
(jak pokazano w moim przykładzie powyżej), oto jak możesz zwrócić trzy wiersze danych z xml cytowanego w pytaniu:
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)