从SQL Server 2008中的XML字段中选择值

Lar*_*nal 103 xml sql-server xpath

只看我的XML字段,我的行看起来像这样:

<person><firstName>Jon</firstName><lastName>Johnson</lastName></person>
<person><firstName>Kathy</firstName><lastName>Carter</lastName></person>
<person><firstName>Bob</firstName><lastName>Burns</lastName></person>
Run Code Online (Sandbox Code Playgroud)

请注意,这些是我表中的三行.

我想将SQL结果作为表返回

Jon  | Johnson
Kathy| Carter
Bob  | Burns
Run Code Online (Sandbox Code Playgroud)

什么查询将完成此任务?

Lar*_*nal 150

鉴于XML字段名为'xmlField'...

SELECT 
[xmlField].value('(/person//firstName/node())[1]', 'nvarchar(max)') as FirstName,
[xmlField].value('(/person//lastName/node())[1]', 'nvarchar(max)') as LastName
FROM [myTable]
Run Code Online (Sandbox Code Playgroud)

  • 如果xmlField包含多个<person>元素,则必须使用.nodes()并交叉应用. (16认同)
  • 离奇.这已经被投了102次,但这个答案只返回*first*XML记录中的数据.它指的是一些[myTable]表......它来自哪里?! (2认同)

Rem*_*anu 116

考虑到XML数据来自表'table'并存储在列'field'中:使用XML方法,提取值xml.value(),项目节点xml.nodes(),用于CROSS APPLY连接:

SELECT 
    p.value('(./firstName)[1]', 'VARCHAR(8000)') AS firstName,
    p.value('(./lastName)[1]', 'VARCHAR(8000)') AS lastName
FROM table 
    CROSS APPLY field.nodes('/person') t(p)
Run Code Online (Sandbox Code Playgroud)

你可以抛弃nodes(),cross apply如果每个字段只包含一个元素'person'.如果XML是您选择的变量FROM @variable.nodes(...)而您不需要cross apply.

  • 请记住,如果您的XML定义了xmlns名称空间,则需要在上面的XQuery(XPath)表达式中定义它们.有关示例,请参见http://stackoverflow.com/a/1302150/656010. (2认同)

小智 16

这篇文章有助于解决我的问题,它有一些不同的XML格式......我的XML包含一个键列表,如下例所示,我将XML存储在名为DeleteBatch的表中的SourceKeys列中:

<k>1</k>
<k>2</k>
<k>3</k>
Run Code Online (Sandbox Code Playgroud)

创建表并使用一些数据填充它:

CREATE TABLE dbo.DeleteBatch (
    ExecutionKey INT PRIMARY KEY,
    SourceKeys XML)

INSERT INTO dbo.DeleteBatch ( ExecutionKey, SourceKeys )
SELECT 1, 
    (CAST('<k>1</k><k>2</k><k>3</k>' AS XML))

INSERT INTO dbo.DeleteBatch ( ExecutionKey, SourceKeys )
SELECT 2, 
    (CAST('<k>100</k><k>101</k>' AS XML))
Run Code Online (Sandbox Code Playgroud)

这是我从SQL中选择键的SQL:

SELECT ExecutionKey, p.value('.', 'int') AS [Key]
FROM dbo.DeleteBatch
    CROSS APPLY SourceKeys.nodes('/k') t(p)
Run Code Online (Sandbox Code Playgroud)

这是查询结果......

ExecutionKey    Key
1   1
1   2
1   3
2   100
2   101


Mar*_*eli 9

这可以回答你的问题:

select cast(xmlField as xml) xmlField into tmp from (
select '<person><firstName>Jon</firstName><lastName>Johnson</lastName></person>' xmlField
union select '<person><firstName>Kathy</firstName><lastName>Carter</lastName></person>'
union select '<person><firstName>Bob</firstName><lastName>Burns</lastName></person>'
) tb

SELECT
    xmlField.value('(person/firstName)[1]', 'nvarchar(max)') as FirstName
    ,xmlField.value('(person/lastName)[1]', 'nvarchar(max)') as LastName
FROM tmp

drop table tmp
Run Code Online (Sandbox Code Playgroud)


Mik*_*ill 6

布里米 这是一个非常有用的发现线程。

我仍然发现其中一些建议令人困惑。每当我在字符串中使用valuewith [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)
Run Code Online (Sandbox Code Playgroud)

这是输出:

在此处输入图片说明

这是一种奇怪的语法,但是有一个不错的示例,将它添加到您自己的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)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明