当有多个属性时,通过 sql 查询从 xml 获取值

get values from xml by sql query when several attributes

xml 有多个属性 "Num"

DECLARE @XML XML = '
<FileId global_id="1234">
  <file id="12aa">
  </file>
  <file id="12bb">
    <Number Num = "1"/>
    <Number Num = "2"/>
  </file>
</FileId>';

用这个sql查询只能得到一个属性

SELECT F.[File].value(N'../@global_id','varchar(100)') as id_payment,
  F.[File].value('@id', 'varchar(4)') AS id,
  F.[File].value('(Number/@Num)[1]', 'int') as [Num]
FROM (VALUES (@XML)) V (X)
  CROSS APPLY V.X.nodes('/FileId/file') F([File]) 

如何获取所有属性 -- Num = 1 和 Num = 2。 可以是可变数量的属性。

id_payment  id      Num
1234        12aa    NULL
1234        12bb    1
1234        12bb    2
DECLARE @XML XML = '
<FileId global_id="1234">
  <file id="12aa">
  </file>
  <file id="12bb">
    <Number Num = "1"/>
    <Number Num = "2"/>
    <Number Num = "3"/>
    <Number Num = "4"/>
    <Number Num = "5"/>
    <Number Num = "6"/>
  </file>
</FileId>';



SELECT F.[File].value(N'../@global_id','varchar(100)') as id_payment,
  F.[File].value('@id', 'varchar(4)') AS id,
  F.[File].value('(Number/@Num)[1]', 'int') as [Num],
  n.num.value('(@Num)[1]', 'int') as [Numxyz]

FROM (VALUES (@XML)) V (X)
  CROSS APPLY V.X.nodes('/FileId/file') F([File]) 
  outer apply F.[File].nodes('Number') as n(num)

更简单的版本。 (1) 不需要使用VALUES 子句。 (2) OUTER APPLY模拟LEFT OUTER JOIN。 (3) 检索 global_id 属性的最有效方法。感谢 Shnugo。

SQL

DECLARE @XML XML = N'
<FileId global_id="1234">
    <file id="12aa">
    </file>
    <file id="12bb">
        <Number Num="1"/>
        <Number Num="2"/>
    </file>
</FileId>';

SELECT @xml.value('(/FileId/@global_id)[1]','INT') AS id_payment
    , c.value('@id', 'VARCHAR(4)') AS id
    , n.value('@Num', 'INT') AS [Num]
FROM @xml.nodes('/FileId/file') AS t(c)
    OUTER APPLY t.c.nodes('Number') AS t2(n);

Output

+------------+------+------+
| id_payment |  id  | Num  |
+------------+------+------+
|       1234 | 12aa | NULL |
|       1234 | 12bb | 1    |
|       1234 | 12bb | 2    |
+------------+------+------+