【问题标题】:Missing elements in T-SQL OPENXML QueryT-SQL OPENXML 查询中缺少元素
【发布时间】:2020-06-10 13:08:14
【问题描述】:

上下文: 我有一个 XML 文档,其结构如下,我通过 OPENXML 在 SQL Server 中查询。我能够查询文档中的几乎所有元素,除了几个 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 查询中添加/更改什么逻辑来捕获 3 个 Line_Items 子元素中的每个子元素中的所有数据吗?下面的查询只返回第一个。我希望以表格形式获取 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

【问题讨论】:

  • 你为什么不使用 XQUERY?
  • 另外,您所追求的预期结果是什么?
  • @Larnu,也许是因为我不知道 XQUERY --__-- 如果您能提供任何帮助,将不胜感激。

标签: sql-server xml tsql xml-parsing openxml


【解决方案1】:

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

大约 15 年以来,SQL-Server 支持 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() 将重复元素(您的&lt;Line_Items&gt;)作为派生集返回。

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 作为目标类型。

【讨论】:

  • 好答案,我这边+1!
猜你喜欢
  • 1970-01-01
  • 2017-03-29
  • 2021-12-05
  • 1970-01-01
  • 2021-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-29
相关资源
最近更新 更多