从SQL Server 2008表中的XML字段中提取属性

Jam*_* L. 28 xml-attribute sql-server-2008

我有一个包含多个列的表,其中一xml列是一列.我没有在查询中使用的命名空间.对于所有记录,XML数据始终是相同的结构.

受控数据

create table #temp (id int, name varchar(32), xml_data xml)

insert into #temp values
(1, 'one',   '<data><info x="42" y="99">Red</info></data>'),
(2, 'two',   '<data><info x="27" y="72">Blue</info></data>'),
(3, 'three', '<data><info x="16" y="51">Green</info></data>'),
(4, 'four',  '<data><info x="12" y="37">Yellow</info></data>')
Run Code Online (Sandbox Code Playgroud)

期望的结果

Name    Info.x   Info.y   Info
-----   -------  -------  -------
one       42       99     Red
two       27       72     Blue
three     16       51     Green
four      12       37     Yellow
Run Code Online (Sandbox Code Playgroud)

部分工作

select Name, xml_data.query('/data/info/.').value('.', 'varchar(10)') as [Info]
from   #temp
Run Code Online (Sandbox Code Playgroud)

它返回NameInfo列.我无法弄清楚如何在不使用命名空间的情况下提取属性值.例如,以下查询返回错误:

查询1

select Name, xml_data.query('/data/info/@x') as [Info]
from   #temp

Msg 2396, Level 16, State 1, Line 12
XQuery [#temp.xml_data.query()]: Attribute may not appear outside of an element
Run Code Online (Sandbox Code Playgroud)

查询2

select Name, xml_data.value('/data/info/@x', 'int') as [Info]
from   #temp

Msg 2389, Level 16, State 1, Line 12
XQuery [#temp.xml_data.value()]: 'value()' requires a singleton (or empty sequence), found operand of type 'xdt:untypedAtomic *'
Run Code Online (Sandbox Code Playgroud)

查询3

select Name, xml_data.query('/data/info/.').value('@x', 'int') as [Info]
from   #temp

Msg 2390, Level 16, State 1, Line 9
XQuery [value()]: Top-level attribute nodes are not supported
Run Code Online (Sandbox Code Playgroud)

如何编写查询以从xml同一个表中的列返回常规列数据和元素+属性值?

Jam*_* L. 39

就在我发布问题之后,我偶然发现了这个问题.不知道为什么我在以前的搜索中找不到它.这是我正在寻找的答案.这是有效的查询:

询问

select Name
      ,xml_data.value('(/data/info/@x)[1]', 'int') as [Info.x]
      ,xml_data.value('(/data/info/@y)[1]', 'int') as [Info.y]
      ,xml_data.value('(/data/info/.)[1]', 'varchar(10)') as [Info]
from   #temp
Run Code Online (Sandbox Code Playgroud)

结果

Name     Info.x    Info.y    Info
-------  --------  --------  ---------
one         42        99     Red
two         27        72     Blue
three       16        51     Green
four        12        37     Yellow
Run Code Online (Sandbox Code Playgroud)

.

------编辑[2014-01-29] ------

我找到了另一个值得添加到这个答案的案例.给定<info>元素中的多个元素<data>,可以<info>使用cross apply以下命令返回所有节点:

create table #temp (id int, name varchar(32), xml_data xml)

insert into #temp values
(1, 'one',   '<data><info x="42" y="99">Red</info><info x="43" y="100">Pink</info></data>'),
(2, 'two',   '<data><info x="27" y="72">Blue</info><info x="28" y="73">Light Blue</info></data>'),
(3, 'three', '<data><info x="16" y="51">Green</info><info x="17" y="52">Orange</info></data>'),
(4, 'four',  '<data><info x="12" y="37">Yellow</info><info x="13" y="38">Purple</info></data>')

select Name
      ,C.value('@x', 'int') as [Info.x]
      ,C.value('@y', 'int') as [Info.y]
      ,C.value('.', 'varchar(10)') as [Info]
from #temp cross apply
     #temp.xml_data.nodes('data/info') as X(C)

drop table #temp
Run Code Online (Sandbox Code Playgroud)

此示例返回以下数据集:

Name      Info.x      Info.y      Info
--------- ----------- ----------- ----------
one       42          99          Red
one       43          100         Pink
two       27          72          Blue
two       28          73          Light Blue
three     16          51          Green
three     17          52          Orange
four      12          37          Yellow
four      13          38          Purple
Run Code Online (Sandbox Code Playgroud)

  • +1.使用`.value`时,必须使用xPath表达式指定单个值.您知道XML中只有一个值,但SQL Server不知道,因此您需要指定您希望使用`[1]`找到第一个值. (4认同)