Получить значения из XML в реляционную таблицу - PullRequest
0 голосов
/ 30 октября 2019

Проблема с преобразованием xml в таблицу. Использовать mssql server 2017. Пример XML:

DECLARE @XML XML = '<file id="12aa"><vd>3</vd>
    <pl_a type_a ="111" k="111" name="aaa"></pl_a>
    <period from="2019-04-01" to="2019-06-30"></period>
    <all>1</all>
  </file>
  <file id="12bb"><vd>3</vd>
    <pl_b type_b ="222" k="222" name="bbb"></pl_b>
    <period from="2019-04-01" to="2019-06-30"></period>
    <all>2</all>
  </file>'

Я пробовал этот запрос:

SELECT
  a.c.value(N'@id',N'nvarchar(150)') as ID,
  a.c.value(N'@type_a',N'nvarchar(150)') as type_a,
  a.c.value(N'@type_b',N'nvarchar(150)') as type_b,
  a.c.value(N'@k',N'nvarchar(150)') as k,
  a.c.value(N'@name',N'nvarchar(150)') as name,
  a.c.value(N'@from',N'nvarchar(150)') as dt_from,
  a.c.value(N'@to',N'nvarchar(150)') as dt_to,
  a.c.value(N'@all',N'nvarchar(150)') as all_
FROM 
@XML.nodes('file') AS a(c) 

Но запрос не получает значения из вложенных всех тегов и атрибутов.

Ожидаемое:

ID    type_a type_b k    name dt_from    dt_to      all_
----- ------ ------ ---- ---- ---------- ---------- ----
12aa  111    NULL   111  aaa  2019-04-01 2019-06-30 1
12bb  NULL   222    222  bbb  2019-04-01 2019-06-30 2

1 Ответ

1 голос
/ 30 октября 2019

Это кажется тем, что вам нужно, но предполагает, что ваши ожидаемые результаты неверны в отношении значений для type_a и type_b:

DECLARE @XML xml = '<file id="12aa">
  <vd>3</vd>
  <pl_a type_a="111" k="111" name="aaa" />
  <period from="2019-04-01" to="2019-06-30" />
  <all>1</all>
</file>
<file id="12bb">
  <vd>3</vd>
  <pl_b type_b="222" k="222" name="bbb" />
  <period from="2019-04-01" to="2019-06-30" />
  <all>2</all>
</file>';

SELECT F.[File].value('@id', 'varchar(4)') AS id,
       ISNULL(F.[File].value('(pl_a/@type_a)[1]', 'int'), F.[File].value('(pl_b/@type_a)[1]', 'int')) AS type_a,
       ISNULL(F.[File].value('(pl_a/@type_b)[1]', 'int'), F.[File].value('(pl_b/@type_b)[1]', 'int')) AS type_b,
       ISNULL(F.[File].value('(pl_a/@k)[1]', 'int'), F.[File].value('(pl_b/@k)[1]', 'int')) AS k,
       ISNULL(F.[File].value('(pl_a/@name)[1]', 'varchar(4)'), F.[File].value('(pl_b/@name)[1]', 'varchar(4)')) AS [name],
       F.[File].value('(period/@from)[1]', 'date') AS [date_from],
       F.[File].value('(period/@to)[1]', 'date') AS [date_from],
       F.[File].value('(all/text())[1]', 'int') AS [all]
FROM (VALUES (@XML)) V (X)
     CROSS APPLY V.X.nodes('/file') F([File]);

Возвращает:

id   type_a      type_b      k           name date_from  date_from  all
---- ----------- ----------- ----------- ---- ---------- ---------- -----------
12aa 111         NULL        111         aaa  2019-04-01 2019-06-30 1
12bb NULL        222         222         bbb  2019-04-01 2019-06-30 2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...