получить значения из xml по запросу sql, когда несколько атрибутов - PullRequest
0 голосов
/ 20 февраля 2020

Существует 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

Ответы [ 2 ]

3 голосов
/ 20 февраля 2020

Гораздо более простая версия. (1) Нет необходимости использовать предложение VALUES. (2) OUTER APPLY имитирует LEFT OUTER JOIN. (3) Наиболее эффективный способ получения атрибута global_id . Кредит идет Шну go.

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);

Выход

+------------+------+------+
| id_payment |  id  | Num  |
+------------+------+------+
|       1234 | 12aa | NULL |
|       1234 | 12bb | 1    |
|       1234 | 12bb | 2    |
+------------+------+------+
2 голосов
/ 20 февраля 2020
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)
...