【问题标题】:Issues Parsing XML data in SQL Server在 SQL Server 中解析 XML 数据的问题
【发布时间】:2015-08-14 23:15:28
【问题描述】:

我在尝试在 SQL Server 中解析一些运输详细信息(发送给我们 ax XML)时遇到了一些困难。

XML结构如下:

<Parent>
    <ShipmentNotice>
        <VendorSKU>ABC123</VendorSKU>
            <SerialNumbers>
                <string>AAAABBBB</string>
                <string>11112222</string>
                <string>CCCCDDDD</string>
                <string>33334444</string>
            </SerialNumbers>
        </VendorSKU>
    </ShipmentNotice>
    <ShipmentNotice>
        <VendorSKU>123ABC</VendorSKU>
            <SerialNumbers>
                <string>EEEEFFFF</string>
                <string>55556666</string>
                <string>GGGGHHHH</string>
                <string>77778888</string>
            </SerialNumbers>
        </VendorSKU>
    </ShipmentNotice>
</Parent>

基本上每个发送的产品实例都有两个&lt;string&gt;标签(AAAABBBB,11112222)。我要做的是解析 XML 并根据我提供的 VendorSKU 为每个 &lt;string&gt; 对创建一行。

到目前为止我所拥有的是:

SELECT
   #ShippingRequests.[xmlcontent].value('(Parent/ShipmentNotice/VendorSKU)[1]', 'varchar(max)') AS VendorSKU,
   #ShippingRequests.[xmlcontent].value('(Parent/ShipmentNotice/SerialNumbers/string)[1]', 'varchar(max)') AS ICCID, 
    #ShippingRequests.[xmlcontent].value('(Parent/ShipmentNotice/SerialNumbers/string)[2]', 'varchar(max)') AS IMEI 
FROM
    (SELECT 
        StoreID, CAST(REPLACE(CAST([RequestData] as NVARCHAR(MAX)), '<User=/>', '') AS XML) AS xmlcontent 
     FROM 
        #ShippingRequests) #ShippingRequests
--CROSS APPLY #ShippingRequests.xmlcontent.nodes('(Parent/ShipmentNotice/SerialNumbers/string)') AS t(c)
WHERE 
    #ShippingRequests.xmlcontent.value('(Parent/ShipmentNotice/VendorSKU)[1]', 'varchar(max)') = 'ABC123'

在没有CROSS APPLY 的情况下运行此程序,会出现两个问题:

  1. 我只得到第一对&lt;string&gt;
  2. 结果仅显示 VendorSKU ABC123 是否是第一个 &lt;ShipmentNotice&gt; 标记的一部分。如果 VendorSKU ABC123 是下一个要解析的 XML 中的第二个 &lt;ShipmentNotice&gt;,则不会显示任何内容。

使用CROSS APPLY 运行此程序,我得到了大量重复项。

如何让此查询针对所有 &lt;string&gt; 对运行,并且无论 VendorSKU 在 XML 中显示的位置如何都运行?

【问题讨论】:

  • 您使用的是什么 SQL 方言?甲骨文、SQL Server、PostgreSQL?请在帖子中标记或提及。

标签: sql sql-server xml xquery


【解决方案1】:

这是一种可能的方式。分解&lt;ShipmentNotice&gt; 元素上的 XML 数据,并应用 VendorSKU 检查分解的 XML 而不是原始 XML 列,如下所示:

.......
CROSS APPLY #ShippingRequests.xmlcontent.nodes('(Parent/ShipmentNotice)') AS t(c)
WHERE c.value('(VendorSKU)[1]', 'varchar(max)') = '123ABC'

请注意,发布的 XML 示例格式不正确,因为它有太多的 VendorSKU 结束标记。这是删除多余的结束标签后的working demo 示例:

declare @ShippingRequests TABLE(StoreID int, RequestData XML)
insert into @ShippingRequests values(1, '<Parent>
    <ShipmentNotice>
        <VendorSKU>ABC123</VendorSKU>
            <SerialNumbers>
                <string>AAAABBBB</string>
                <string>11112222</string>
                <string>CCCCDDDD</string>
                <string>33334444</string>
            </SerialNumbers>
    </ShipmentNotice>
    <ShipmentNotice>
        <VendorSKU>123ABC</VendorSKU>
            <SerialNumbers>
                <string>EEEEFFFF</string>
                <string>55556666</string>
                <string>GGGGHHHH</string>
                <string>77778888</string>
            </SerialNumbers>
    </ShipmentNotice>
</Parent>')
SELECT
c.value('(VendorSKU)[1]', 'varchar(max)') AS VendorSKU,
c.value('(SerialNumbers/string)[1]', 'varchar(max)') AS ICCID, 
c.value('(SerialNumbers/string)[2]', 'varchar(max)') AS IMEI 
FROM
(
   SELECT 
   StoreID, CAST(REPLACE(CAST([RequestData] as NVARCHAR(MAX)), '<User=/>', '') AS XML) AS xmlcontent 
   FROM 
   @ShippingRequests
) 
#ShippingRequests
CROSS APPLY #ShippingRequests.xmlcontent.nodes('(Parent/ShipmentNotice)') AS t(c)
WHERE c.value('(VendorSKU)[1]', 'varchar(max)') = '123ABC' --'ABC123'

输出:

| VendorSKU |    ICCID |     IMEI |
|-----------|----------|----------|
|    123ABC | EEEEFFFF | 55556666 |

【讨论】:

    猜你喜欢
    • 2023-03-17
    • 2013-02-21
    • 2021-11-04
    • 2013-03-18
    • 1970-01-01
    • 2023-03-19
    • 2019-12-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多