2015-08-14 77 views
1

我在尝试解析SQL Server中的一些送货细节(发送给我们ax XML)时遇到了一些困难。解析SQL Server中的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> 

本质上正在发送的产品的每一种情况下具有每例如两个<string>标签(AAAABBBB,11112222)。我期望做的是通过XML解析并根据我提供的VendorSKU为每个<string>对创建一行。

我至今是:

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. 我只得到了第一<string>
  2. 一个结果只显示如果VendorSKU ABC123是第一个<ShipmentNotice>标签的一部分。如果VendorSKU ABC123第二个<ShipmentNotice>在下一个XML中解析,那么什么都不显示。

CROSS APPLY一起运行,我得到了大量的重复。

无论VendorSKU在XML中显示的位置是什么,我如何获得此查询以运行所有<string>对并运行?

+1

什么SQL方言是您使用? Oracle,SQL Server,PostgreSQL?请在帖子中标记或提及。 – Parfait

回答

0

这是一种可能的方法。切丝上<ShipmentNotice>元素的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 |