Получить значение из корневого элемента xml в столбец - PullRequest
3 голосов
/ 30 октября 2019

Проблема с добавлением корневого элемента. Использовать mssql server 2017. Пример XML:

DECLARE @XML XML = '
<FileId global_id="1234">
  <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>
</FileId>'

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

SELECT F.[File].value(N'@global_id','varchar(100)') as id_payment,
       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('/FileId/file') F([File]);

Но запрос не получает корневое значение.

Ожидается:

global_id id   type_a      type_b      k           name date_from  date_from  all
--------- ---- ----------- ----------- ----------- ---- ---------- ---------- -----------
1234      12aa 111         NULL        111         aaa  2019-04-01 2019-06-30 1
1234      12bb NULL        222         222         bbb  2019-04-01 2019-06-30 2

Факт:

global_id id   type_a      type_b      k           name date_from  date_from  all
--------- ---- ----------- ----------- ----------- ---- ---------- ---------- -----------
NULL      12aa 111         NULL        111         aaa  2019-04-01 2019-06-30 1
NULL      12bb NULL        222         222         bbb  2019-04-01 2019-06-30 2

Ответы [ 2 ]

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

Изменить это:

SELECT F.[File].value(N'@global_id','varchar(100)') as id_payment

На это:

SELECT V.X.value(N'(/FileId/@global_id)[1]','varchar(100)') as id_payment
2 голосов
/ 30 октября 2019

Вы можете использовать ../, чтобы получить родительский узел текущего узла контекста. Таким образом, вы можете использовать ../@global_id вместо @global_id, чтобы получить значение атрибута родительского элемента (Fileid):

-- XML document
DECLARE @XML XML = '
<FileId global_id="1234">
  <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>
</FileId>';

-- SELECT to get some information of the XML document
SELECT F.[File].value(N'../@global_id','varchar(100)') as id_payment,
  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('/FileId/file') F([File]);

demo на dbfiddle.uk

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...