Blimey. Это была действительно полезная тема для открытия.
Я все еще находил некоторые из этих предложений запутанными. Всякий раз, когда я использовал value
с [1]
в строке, он получал только первое значение. И некоторые предложения рекомендовали использовать cross apply
, который (в моих тестах) просто возвращал слишком много данных.
Итак, вот мой простой пример того, как вы бы создали xml
объект, а затем считали его значения в таблицу.
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)
А вот и вывод:
Это странный синтаксис, но на приличном примере его достаточно легко добавить к собственным функциям SQL Server.
Кстати, вот правильный ответ на этот вопрос:
Предполагая, что ваши данные xml хранятся в переменной @xml
типа xml
(как показано в моем примере выше), вот как вы должны вернуть три строки данных из xml, указанных в вопросе:
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)