2

これが私のシナリオです:

--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>

プロセスのある時点で、これらの注文のそれぞれの追跡番号を知ることができます。追跡番号は、次のような別の表で利用できます。

 --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>`

ご覧のとおり、TrackingNumberDateShippedfor eachを取得OrderCodeして属性として持たせようとしています。意図は、UPDATE ではなく SELECT です。

私が見たすべての例は、XML を定数値または変数で更新する方法を示しています。JOIN を使用した XML 更新を示すものは見つかりませんでした。これを達成する方法を教えてください。

アップデート:

「Select not Update」とは、永続テーブルを更新しないことを意味します。Mikael が最初の回答の下にコメントしたように、一時テーブルの UPDATE はまったく問題ありません。

4

3 に答える 3

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を参照してください

于 2013-08-07T06:09:36.973 に答える
3

XML に属性を追加するために一時テーブルを使用するバージョン。

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
于 2013-08-07T06:58:19.647 に答える
1

xmlタイプの列のデータの部分的な変更を許可する唯一の方法はmodifyメソッドを使用することですが、ドキュメントに記載されているように

xml データ型の modify() メソッドは、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

于 2013-08-06T22:16:07.553 に答える