通过 OPENXML SQL Server 2008 解析 XML

Parse XML via OPENXML SQL Server 2008

上下文: 我在下面有一个 XML 文档,我正试图在 SQL Server 2008 中查询它。我已按照此处的提示进行操作: https://www.youtube.com/watch?v=vy2Nv26UzAU 并有一个执行无误的查询,但是 returns 在显然不为空的字段中出现空值。

问题:有人可以提供一些 pointers/troubleshooting 提示来说明为什么查询返回空结果吗?这是层次结构路径或数据类型的问题吗?

这是 XML 文档:

<Order_Details>
<Selection_ID>2100</Selection_ID>
<Order_Details>
  <Able_To_Use>Y</Able_To_Use>
  <Purchase_ID>GF-00000001</Purchase_ID>
  <QTY>1</QTY>
  <Subdetails>
    <REGION_QTY>2</REGION_QTY>
    <Testing_NO>00.05.04.01.00</Testing_NO>
  </Subdetails>
</Order_Details>
<Order_Details>
  <Able_To_Use>Y</Able_To_Use>
  <Purchase_ID>GF-00000002</Purchase_ID>
  <QTY>1</QTY>
  <Subdetails>
    <REGION_QTY>2</REGION_QTY>
    <Testing_NO>00.05.04.01.034</Testing_NO>
  </Subdetails>
</Order_Details>

这里是查询:

--Declare a table variable to hold the data in single column of XML data type
DECLARE @xml_data XML

SELECT @xml_data=O
FROM OPENROWSET(BULK N'C:\Users\Desktop\Important Docs & Links\Important     Documents\Python Scripts\separate_xml_doc.xml', SINGLE_BLOB) as file_output(O)

DECLARE @xml_doc int

--Procedure below takes 2 parameters: 1) output parameter to store handle to xml document and 2) the xml document itself 
EXEC sp_xml_preparedocument @xml_doc OUTPUT, @xml_data

SELECT *
FROM OPENXML(@xml_doc,'/Order_Details/Order_Details/',2)
WITH (
        Able_To_Use nvarchar(10),
        Purchase_ID nvarchar(20),
        QTY int
        )

--This procedre removes the saved prepared xml document from memory once finished using 
EXEC sp_xml_removedocument @xml_doc

这些是结果:

要想获得自己的尝试运行,无非就是/到:

FROM OPENXML(@xml_doc,'/Order_Details/Order_Details',2)

但是这种做法已经过时了。 FROM OPENXML,与 SP 一起准备和删除文档不应再使用(存在极少数例外)。

XML(自 v2005 :-))的现代方法是使用原生 XML 方法,XML 类型提供:

--Declare a table variable to hold the data in single column of XML data type
DECLARE @xml_data XML

SELECT @xml_data=
N'<Order_Details>
<Selection_ID>2100</Selection_ID>
<Order_Details>
  <Able_To_Use>Y</Able_To_Use>
  <Purchase_ID>GF-00000001</Purchase_ID>
  <QTY>1</QTY>
  <Subdetails>
    <REGION_QTY>2</REGION_QTY>
    <Testing_NO>00.05.04.01.00</Testing_NO>
  </Subdetails>
</Order_Details>
<Order_Details>
  <Able_To_Use>Y</Able_To_Use>
  <Purchase_ID>GF-00000002</Purchase_ID>
  <QTY>1</QTY>
  <Subdetails>
    <REGION_QTY>2</REGION_QTY>
    <Testing_NO>00.05.04.01.034</Testing_NO>
  </Subdetails>
</Order_Details>
</Order_Details>';

--查询

SELECT @xml_data.value('(/Order_Details/Selection_ID/text())[1]','int') AS SelectionId
      ,od.value('(Able_To_Use/text())[1]','nchar(1)') AS AbleToUse
      ,od.value('(Purchase_ID/text())[1]','nvarchar(10)') AS PurchaseId
      ,od.value('(QTY/text())[1]','int') AS Quantity
      ,od.value('(Subdetails/REGION_QTY/text())[1]','int') AS RegionQty
      ,od.value('(Subdetails/Testing_NO/text())[1]','nvarchar(10)') AS TestingNo
FROM @xml_data.nodes('/Order_Details/Order_Details') A(od)

我在这里选择不同的级别。

  • Selection_ID可以直接从变量中取
  • 我们可以使用.nodes()来检索一组重复元素
  • 我们可以使用 .value() 和 XPath 来抓取元素并获取它们的文本节点。

上面的代码是最明确的。这可以说得更简单,但最好使用 XML 使其尽可能明确。只是为了演示,什么会起作用:

此查询具有相同的结果,但推荐...

SELECT @xml_data.value('(//Selection_ID)[1]','int') AS SelectionId
      ,od.value('Able_To_Use[1]','nchar(1)') AS AbleToUse
      ,od.value('Purchase_ID[1]','nvarchar(10)') AS PurchaseId
      ,od.value('QTY[1]','int') AS Quantity
      ,od.value('(Subdetails/REGION_QTY)[1]','int') AS RegionQty
      ,od.value('(Subdetails/Testing_NO)[1]','nvarchar(10)') AS TestingNo
FROM @xml_data.nodes('/Order_Details/Order_Details') A(od)