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>

在此过程中的某个时刻,我会知道这些订单的相应 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>`

如您所见,我正在尝试为每个获取 theTrackingNumber和 the并将它们作为属性。意图是 SELECT,而不是 UPDATE。DateShippedOrderCode

我看到的所有示例都演示了如何使用常量值或变量更新 XML。我找不到使用 JOIN 演示 XML 更新的工具。请帮助如何实现这一点。

更新:

通过“选择不更新”,我的意思是永久表没有更新;正如 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 回答