从 SQL XML 字段中提取值

Mik*_*son 6 xml sql sql-server xpath

使用 MS SQL Server,我在 XML 字段(称为XML)中获取了一些数据,其结构如下:

<Transaction01>
  <TransactionSetPurpose>Insert</TransactionSetPurpose>
  <POHeader>
    <PO_NBR>LG40016181</PO_NBR>
  </POHeader>
</Transaction01>
Run Code Online (Sandbox Code Playgroud)

我正在尝试创建一个 SQL 查询来获取另一个名为 SubmittedDate 的列,以及此 XML 字段中的 PO_NBR。作为 XPath 的新手,我阅读了大量示例并尝试了queryvalue,但还没有成功。例如:

SELECT SubmittedDate, 
       XML.query('data(/POHeader/PO_NBR)') as PO_NBR
  FROM SubmitXML
Run Code Online (Sandbox Code Playgroud)

这只是给了我一个空列。在从 Quassnoi 获得工作测试后,我从他的 XML 开始工作,发现问题出在根节点中的 xmlns 和 xmlns:i 属性:

<Transaction01 xmlns="http://services.iesltd.com/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
Run Code Online (Sandbox Code Playgroud)

那么我该如何解决这个问题呢?

Qua*_*noi 6

SELECT  SubmittedDate, 
        XML.query('data(/Transaction01/POHeader/PO_NBR)') as PO_NBR
FROM    SubmitXML
Run Code Online (Sandbox Code Playgroud)

您最初XPath, /POHeader/PO_NBR, 假设POHeader是根节点(实际上不是)。

要检查的示例查询:

DECLARE @myxml XML
SET @myxml = '
<Transaction01>
  <TransactionSetPurpose>Insert</TransactionSetPurpose>
  <POHeader>
    <PO_NBR>LG40016181</PO_NBR>
  </POHeader>
</Transaction01>'

SELECT  @myxml.query('data(/Transaction01/POHeader/PO_NBR)')
Run Code Online (Sandbox Code Playgroud)

如果Transaction01不总是根节点(这不是一件好事),请使用:

SELECT  SubmittedDate, 
        XML.query('data(/*/POHeader/PO_NBR)') as PO_NBR
FROM    SubmitXML
Run Code Online (Sandbox Code Playgroud)

一般来说,XML模式假设标签名称是固定的,可变部分指向节点和属性的数据,而不是它们的名称,如下所示:

<Transaction id='01'>
  <TransactionSetPurpose>Insert</TransactionSetPurpose>
  <POHeader>
    <PO_NBR>LG40016181</PO_NBR>
  </POHeader>
</Transaction>
Run Code Online (Sandbox Code Playgroud)

更新:

您应该使用以下方式声明名称空间WITH XMLNAMESPACES

DECLARE @myxml XML
SET @myxml = '
<Transaction01 xmlns="http://services.iesltd.com/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <TransactionSetPurpose>Insert</TransactionSetPurpose>
  <POHeader>
    <PO_NBR>LG40016181</PO_NBR>
  </POHeader>
</Transaction01>'

;
WITH    XMLNAMESPACES
        (
        'http://services.iesltd.com/' AS m
        )
SELECT  @myxml.query
        (
        'data(/*/m:POHeader/m:PO_NBR)'
        )
Run Code Online (Sandbox Code Playgroud)

更新2:

排序:

;
WITH    XMLNAMESPACES
        (
        'http://services.iesltd.com/' AS m
        )
SELECT  SubmittedDate, 
        XML.value('(/*/m:POHeader/m:PO_NBR)[1]', 'NVARCHAR(200)') AS po_nbr
FROM    SubmitXML
ORDER BY
        po_nbr
Run Code Online (Sandbox Code Playgroud)