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
作为目标类型
上下文: 我有一个 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
作为目标类型