2015-08-14 50 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 |