Как вставить xml узлы с тем же именем и игнорировать на основе атрибута - PullRequest
0 голосов
/ 09 мая 2020

У меня есть ниже xml

`

<xml>
<entities>
<entity id="147297" version="20150209161956">
    <dobs>
        <dob Y="1970">10/16/1970</dob>
        <dob D="17" M="10" Y="1970">10/17/1970</dob>
        <dob D="02" M="7" Y="1920">02/1]7/1920</dob>
        <dob D="1" M="9" Y="1990">10/9/1990</dob>
        <dob Y="1870">10/16/1870</dob>
    </dobs>
</entity>
</entities>
</xml>

`

Мне нужно вставить только узлы dob, которые имеют атрибуты D и M и Y в table (Таблица A), если указан только атрибут Y, тогда весь тег необходимо вставить в другую таблицу (Таблица B), как этого добиться: SQL.

Спасибо за ваши предложения

1 Ответ

0 голосов
/ 11 мая 2020

Вы ищете что-то подобное?

DECLARE @xml XML=
N'<xml>
<entities>
<entity id="147297" version="20150209161956">
    <dobs>
        <dob Y="1970">10/16/1970</dob>
        <dob D="17" M="10" Y="1970">10/17/1970</dob>
        <dob D="02" M="7" Y="1920">02/1]7/1920</dob>
        <dob D="1" M="9" Y="1990">10/9/1990</dob>
        <dob Y="1870">10/16/1870</dob>
    </dobs>
</entity>
</entities>
</xml>';

- полные добы для таблицы A

SELECT ent.value('@id','int') AS Entity_Id
      ,ent.value('@version','nvarchar(max)') AS Entity_Version
      ,AllParams.query('.')
FROM @xml.nodes('/xml/entities/entity') A(ent)
OUTER APPLY A.ent.nodes('dobs/dob[@D and @M and @Y]') B(AllParams);

- добы только Y для таблицы B

SELECT ent.value('@id','int') AS Entity_Id
      ,ent.value('@version','nvarchar(max)') AS Entity_Version
      ,JustY.query('.')
FROM @xml.nodes('/xml/entities/entity') A(ent)
OUTER APPLY A.ent.nodes('dobs/dob[@Y and empty(@M)]') C(JustY);

Оба запроса используют предикат XQuery в .nodes(). Первый запрос вернет <dob> узлов, в которых есть D-, M- и Y-атрибуты. Второй запрос вернет <dob> узлов, где M-атрибут пуст (=> не существует).

Легко собрать значения для вашей вставки. Просто используйте .value() вместо .query() и запросите атрибут, используя, например, @Y, или запросите содержимое узла, используя text():

--complete dobs for Table A
SELECT ent.value('@id','int') AS Entity_Id
      ,ent.value('@version','nvarchar(max)') AS Entity_Version
      ,AllParams.value('@D','int') TheDay
      ,AllParams.value('@M','int') TheMonth
      ,AllParams.value('@Y','int') TheYear
      ,AllParams.value('text()[1]','nvarchar(max)') TheContent
FROM @xml.nodes('/xml/entities/entity') A(ent)
OUTER APPLY A.ent.nodes('dobs/dob[@D and @M and @Y]') B(AllParams);

Подсказка: внутри XML any значение даты / времени должно быть в кодировке ISO8601 (например, 1970-10-17). В противном случае вы открыты для смешения культур ... Более того: с ISO8601 вы можете использовать date в качестве типа данных в .value(), чтобы получить безопасное значение. Без этого вы подвержены ошибкам при приведении ...

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