Недостающие элементы в T- SQL OPEN XML Query - PullRequest
0 голосов
/ 26 февраля 2020

Контекст: У меня есть документ XML со структурой ниже, который я запрашиваю на сервере SQL через OPEN XML. Я могу запросить почти все элементы в документе, за исключением нескольких дочерних элементов, которые OPEN XML по какой-то причине не захватывает.

<HRD>
<Search>ER-0002</Search>
<SubCHD>
<APPR_PROC_CD>ADR</APPR_PROC_CD>
<Line_Items>
<APPRVL_EMPL_ID>119845</APPRVL_EMPL_ID>
<APPRVL_SEQ_NO>23358960</APPRVL_SEQ_NO>
<APPRVL_DTT>2019-18-05T13:19:27</APPRVL_DTT>
</Line_Items>
</Line_Items>
<APPRVL_EMPL_ID>788270</APPRVL_EMPL_ID>
<APPRVL_SEQ_NO>287360</APPRVL_SEQ_NO>
<APPRVL_DTT>2014-11-05T13:19:27</APPRVL_DTT>
</Line_Items>
</Line_Items>
<APPRVL_EMPL_ID>72987437</APPRVL_EMPL_ID>
<APPRVL_SEQ_NO>23484580</APPRVL_SEQ_NO>
<APPRVL_DTT>2013-11-05T13:19:27</APPRVL_DTT>
<Line_Items>
<RQ_Sub>
<Delta>N</Delta>
<LN_Act>
<ACCT_ID>ABDSNJD1267</ACCT_ID>
</LN_Act>
</RQ_Sub>
</SubCHD>
</HRD>

Вопросы: Может кто-нибудь объяснить, какие логики c Мне нужно добавить / изменить в запросе SQL, чтобы собрать все данные в каждом из 3 дочерних элементов Line_Items элементы? Запрос ниже возвращает только первый. Я ожидаю получить полное содержимое XML в табличной форме, аналогично скриншоту ниже, но с дополнительными строками для отсутствующих элементов Line_Items.

enter image description here

EXEC sp_xml_removedocument @reqid_xml_doc


DECLARE @reqid_xml_data XML

SELECT @reqid_xml_data=O
FROM OPENROWSET(BULK N'C:\Users\eb\Desktop\Important_Docs_Links\Important_Documents\req_status_xml_data.xml', SINGLE_BLOB) as file_output(O)

DECLARE @reqid_xml_doc int

EXEC sp_xml_preparedocument @reqid_xml_doc OUTPUT, @reqid_xml_data

SELECT *
FROM OPENXML(@reqid_xml_doc,'HRD/*',2)

WITH (
        APPRVL_EMPL_ID int 'Line_Items/APPRVL_EMPL_ID', 
        APPRVL_SEQ_NO int 'Line_ItemsL/APPRVL_SEQ_NO',
        APPRVL_DTT nvarchar(25)'Line_Items/APPRVL_DTT',

        DELTA nvarchar(15) 'RQ_Sub/DELTA',

        ACCT_ID nvarchar(50) 'RQ_Sub/LN_Act/ACCT_ID'

        )

EXEC sp_xml_removedocument @reqid_xml_doc

1 Ответ

2 голосов
/ 26 февраля 2020

Ваш подход с использованием FROM OPENXML вместе с SP для подготовки и удаления документа устарел и больше не должен использоваться (существуют редкие исключения).

В течение примерно 15 лет SQL -Server поддерживает родные XML методы для XPath и XQuery:

Попробуйте это так (я предполагаю, что содержимое вашего файла загружено в @xml):

(Подсказка: у меня было исправить некоторые ошибки ... Ваш XML не был правильно сформирован ...)

DECLARE @xml XML=
N'<HRD>
  <Search>ER-0002</Search>
  <SubCHD>
    <APPR_PROC_CD>ADR</APPR_PROC_CD>
    <Line_Items>
      <APPRVL_EMPL_ID>119845</APPRVL_EMPL_ID>
      <APPRVL_SEQ_NO>23358960</APPRVL_SEQ_NO>
      <APPRVL_DTT>2019-18-05T13:19:27</APPRVL_DTT>
    </Line_Items>
    <Line_Items>
      <APPRVL_EMPL_ID>788270</APPRVL_EMPL_ID>
      <APPRVL_SEQ_NO>287360</APPRVL_SEQ_NO>
      <APPRVL_DTT>2014-11-05T13:19:27</APPRVL_DTT>
    </Line_Items>
    <Line_Items>
      <APPRVL_EMPL_ID>72987437</APPRVL_EMPL_ID>
      <APPRVL_SEQ_NO>23484580</APPRVL_SEQ_NO>
      <APPRVL_DTT>2013-11-05T13:19:27</APPRVL_DTT>
    </Line_Items>
    <RQ_Sub>
      <Delta>N</Delta>
      <LN_Act>
        <ACCT_ID>ABDSNJD1267</ACCT_ID>
      </LN_Act>
    </RQ_Sub>
  </SubCHD>
</HRD>'; 

- Запрос будет использовать некоторые вызовы .value() для самой переменной (неповторяющиеся элементы ) и будет использовать .nodes() для возврата повторяющихся элементов (вашего <Line_Items>) в качестве производного набора.

SELECT @xml.value('(/HRD/Search/text())[1]','varchar(100)') AS Search
      ,@xml.value('(/HRD/SubCHD/APPR_PROC_CD/text())[1]','varchar(100)') AS ApprProcCd
      ,li.value('(APPRVL_EMPL_ID/text())[1]','bigint') AS EmplId
      ,li.value('(APPRVL_SEQ_NO/text())[1]','bigint') AS SeqNo
      ,li.value('(APPRVL_DTT/text())[1]','varchar(100)') AS Dtt --Attention!!!!!
      ,@xml.value('(/HRD/SubCHD/RQ_Sub/Delta/text())[1]','varchar(100)') AS Delta
      ,@xml.value('(/HRD/SubCHD/RQ_Sub/LN_Act/ACCT_ID/text())[1]','varchar(100)') AS AcctId
FROM @xml.nodes('/HRD/SubCHD/Line_Items') A(li)

Результат

ER-0002 ADR 119845      23358960    2019-18-05T13:19:27 N   ABDSNJD1267
ER-0002 ADR 788270      287360      2014-11-05T13:19:27 N   ABDSNJD1267
ER-0002 ADR 72987437    23484580    2013-11-05T13:19:27 N   ABDSNJD1267

Очень важно: Значения даты и времени выглядят так, как если бы они были ISO8601 (T в середине), но формат даты - ydm, для которого должно быть ymd. В противном случае мы могли бы указать datetime в качестве целевого типа в .value().

...