Tsql 从同一个/另一个表中的另一列向XML列添加属性
以下是我的设想:Tsql 从同一个/另一个表中的另一列向XML列添加属性,tsql,sql-server-2005,sqlxml,Tsql,Sql Server 2005,Sqlxml,以下是我的设想: --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>&
--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>
我期望的输出如下所示:
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>`
OrderID OrderCode ShipmentXML
1 ABC
2 XYZ`
如您所见,我正在尝试获取每个OrderCode
的TrackingNumber
和DateShipped
,并将它们作为属性。目的是选择,而不是更新
我看到的所有示例都演示了如何使用常量值或变量更新XML。我找不到一个用连接来演示XML更新的。请帮助说明如何实现这一点
更新:
通过“选择不更新”,我的意思是不更新永久表;正如Mikael在第一个答案下面所评论的那样,临时表的更新非常好。我所知道的允许部分修改
xml
类型列中数据的唯一方法是使用modify
方法,但如中所述
xml数据类型的modify()方法只能在集合中使用
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上一个答案是好的,但是您必须明确指定列并将它们转换为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
请参见使用临时表将属性添加到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
或者,您可以将行提取到临时表中,并在那里修改XML(两次),然后查询临时表+1i one和Mikael请参见问题的编辑。我也想看看Mikael的方法。@FMFF我添加了一个这样的版本。这两种方法都是重建XML的聪明方法+1.我的+1也是,我还不熟悉这些技术。在特定情况下,各种方法越多,选择就越丰富。@这种方法的一个优点是,XML中可以有任意数量的其他节点,它们仍然会出现在结果中。您的答案和另一个答案都重建了XML,假设问题中的内容就是所有内容。很可能是这样,只有OP知道。+1,是的,如果XML比世界上的XML更丰富,它可能会很有用question@MikaelEriksson你是绝对正确的;Xml很可能在将来与其他节点一起增长。
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
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