2013-08-06 39 views
2

這裏是我的方案添加到XML列的屬性:從另一列在同一個/另一個表

--ORDER table 
OrderID OrderCode DateShipped ShipmentXML 
1  ABC  08/06/2013  <Order><Item CustomerName="BF" City="Philadelphia" State="PA"></Item></Order> 
2  XYZ  08/05/2013  <Order><Item CustomerName="TJ" City="Richmond" State="VA"></Item></Order> 

在過程中的某個時刻,我會知道這些訂單分別TrackingNumber。跟蹤號碼另一個表可用這樣的:

--TRACKING table 
TrackingID OrderCode TrackingNumber  
98   ABC   1Z1    
99   XYZ   1Z2 

我期待的輸出如下:

OrderID OrderCode  ShipmentXML 
    1  ABC   <Order><Item CustomerName="BF" City="Philadelphia" State="PA" DateShipped="08/06/2013" TrackingNumber="1Z1"></Item></Order> 
    2  XYZ   <Order><Item CustomerName="TJ" City="Richmond" State="VA" DateShipped="08/05/2013" TrackingNumber="1Z2"></Item></Order>` 

正如你所看到的,我試圖讓TrackingNumberDateShipped每個OrderCode並將它們作爲屬性。意圖是一個SELECT,而不是UPDATE。

我見過的所有示例演示瞭如何使用常量值或變量更新XML。我無法找到一個用JOIN演示XML更新的人。請幫助完成這項工作。

UPDATE:

通過 '選擇不更新',我的意思是永久表中沒有更新;因爲Mikael在第一個答案下面評論,所以臨時表的更新非常好。

回答

3

一個版本。

select OrderID, 
     OrderCode, 
     DateShipped, 
     ShipmentXML 
into #Order 
from [Order] 

update #Order 
set ShipmentXML.modify 
    ('insert attribute DateShipped {sql:column("DateShipped")} 
    into (/Order/Item)[1]') 

update O 
set ShipmentXML.modify 
    ('insert attribute TrackingNumber {sql:column("T.TrackingNumber")} 
    into (/Order/Item)[1]') 
from #Order as O 
    inner join Tracking as T 
    on O.OrderCode = T.OrderCode 

select OrderID, 
     OrderCode, 
     ShipmentXML 
from #Order 

drop table #Order 
+0

+1。在各種情況下更豐富的選擇更豐富的選擇。 –

+1

@ i-one這種方法的優點是XML可以有任意數量的其他節點,並且它們仍然會在結果中。您和其他答案都重新構建了XML,假定問題中存在的是全部。而且很可能如此,只有OP知道。 –

+0

+1,是的,如果XML比問題 –

1

我知道允許xml類型的列中的數據的部分修改的唯一方法是使用modify的方法,但如在documentation

xml數據類型的修改()方法中規定只能在使用UPDATE語句的SET 子句。

由於UPDATE不理想,作爲一種解決方法我看到的破碎和手動重新組裝爲:

select 
    o.OrderID, 
    o.OrderCode, 
    (
     cast((select 
      t.c.value('@CustomerName', 'varchar(50)') as '@CustomerName', 
      t.c.value('@City', 'varchar(50)') as '@City', 
      t.c.value('@State', 'varchar(50)') as '@State', 
      o.DateShipped as '@DateShipped', 
      tr.TrackingNumber as '@TrackingNumber' 
     for xml path('Item'), root('Order')) as xml) 
    ) as ShipmentXML 
from 
    [ORDER] o 
    join [TRACKING] tr on tr.OrderCode = o.OrderCode 
    cross apply o.ShipmentXML.nodes('Order/Item') t(c) 

您可能需要應用格式o.DateShipped

+1

或者您可以將行提取到臨時表並在那裏修改XML(兩次),然後查詢臨時表。 +1 –

+0

i-one&@Mikael請參閱編輯問題。我很想看到Mikael的方法。 – FMFF

+1

@FMFF我添加了一個版本來做到這一點。 –

3

上面的回答很好,但你必須顯式地指定列並將它們轉換爲varchar,這對於未來的支持不太好(如果向ShipmentXML添加屬性,則必須修改查詢)。
相反,你可以使用XQuery:

select 
    O.OrderID, O.OrderCode, 
    (
     select 
      (select O.DateShipped, T.TrackingNumber for xml raw('Item'), type), 
      O.ShipmentXML.query('Order/*') 
     for xml path(''), type 
    ).query('<Order><Item>{for $i in Item/@* return $i}</Item></Order>') 
from [ORDER] as O 
    left outer join [TRACKING] as T on T.OrderCode = O.OrderCode 
這樣

甚至:

select 
    O.OrderID, O.OrderCode, 
    O.ShipmentXML.query(' 
      element Order { 
       element Item { 
        attribute DateShipped {sql:column("O.DateShipped")}, 
        attribute TrackingNumber {sql:column("T.TrackingNumber")}, 
        for $i in Order/Item/@* return $i 
       } 
      }') 
from [ORDER] as O 
    left outer join [TRACKING] as T on T.OrderCode = O.OrderCode 

看到sqlfiddle使用臨時表的屬性添加到XML實例

+0

這兩種聰明的方式重建XML。 +1。 –

+0

我的+1也是,我對這些技術還不熟悉,但還沒有 –