【问题标题】:Extracting Attributes from XML Fields in SQL Server 2008 Table从 SQL Server 2008 表中的 XML 字段中提取属性
【发布时间】:2013-04-06 04:24:26
【问题描述】:

我有一个包含几列的表,其中之一是 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>')

期望的结果

Name    Info.x   Info.y   Info
-----   -------  -------  -------
one       42       99     Red
two       27       72     Blue
three     16       51     Green
four      12       37     Yellow

部分有效

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

它返回 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

查询 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 *'

查询 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

问题

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

【问题讨论】:

    标签: sql-server-2008 xml-attribute


    【解决方案1】:

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

    查询

    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
    

    结果

    Name     Info.x    Info.y    Info
    -------  --------  --------  ---------
    one         42        99     Red
    two         27        72     Blue
    three       16        51     Green
    four        12        37     Yellow
    

    .

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

    我发现了另一个值得添加到这个答案的案例。给定&lt;data&gt; 元素中的多个&lt;info&gt; 元素,可以使用cross apply 返回所有&lt;info&gt; 节点:

    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
    

    此示例返回以下数据集:

    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
    

    【讨论】:

    • +1。使用 .value 时,您必须使用 xPath 表达式指定单个值。您知道 XML 中的值不超过一个,但 SQL Server 不知道这一点,因此您需要指定要使用 [1] 找到的第一个值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多