T-SQL OPENXML 查询中缺少元素

Missing elements in T-SQL OPENXML Query

上下文: 我有一个 XML 文档,其结构如下,我通过 OPENXML 在 SQL 服务器中查询。除了 OPENXML 出于某种原因未捕获的几个子元素外,我几乎可以查询文档中的所有元素。

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

问题:有人可以解释一下我需要在 SQL 查询中 add/change 什么逻辑来捕获 3 Line_Items子元素?下面的查询只有returns第一个。我希望以表格形式获得 XML 的全部内容,类似于下面的屏幕截图,但有额外的行用于缺少 Line_Items 元素。

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

您使用 FROM OPENXML 和 SP 一起准备和删除文档的方法已经过时,不应再使用(存在极少数例外)。

大约 15 年 SQL-服务器支持 XPath 和 XQuery 的本机 XML 方法:

像这样尝试(我假设您的文件内容已加载到 @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() 到 return 重复元素(您的 <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。否则我们可以在 .value().

中指定 datetime 作为目标类型