这是我的情景:
--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>`
正如您所看到的,我正在尝试为每个TrackingNumber
获取DateShipped
和OrderCode
,并将它们作为属性。意图是SELECT,而不是UPDATE。
我见过的所有示例都演示了如何使用Constant值或变量更新XML。我找不到一个用JOIN演示XML更新的人。请帮助解决这个问题。
更新:
通过“选择不更新”,我的意思是永久表没有更新;临时表的更新完全没问题,正如Mikael在第一个答案下面评论的那样。
答案 0 :(得分:3)
Prevous答案很好,但您必须明确指定列并将它们转换为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示例
答案 1 :(得分: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
答案 2 :(得分:1)
我知道允许对xml
类型列中的数据进行部分修改的唯一方法是使用modify
方法,但正如documentation中所述
xml数据类型的modify()方法只能在SET中使用 UPDATE语句的子句。
由于不需要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
。