假设我有下表(其中History是xml列):
Id Value History
1 "Hello" <History>
<Node date="1-1-2011">World</Node>
<Node date="1-2-2011">Foo</Node>
<Node date="1-3-2011">Bar</Node>
</History>
2 "Baz" <History>
<Node date="1-1-2011">Buzz</Node>
<Node date="1-2-2011">Fizz</Node>
<Node date="1-3-2011">Beam</Node>
</History>
从那时起,我想选择一个新表,如:
HistoryId Id Value Date
1 1 "World" 1-1-2011
2 1 "Foo" 1-2-2011
3 1 "Bar" 1-3-2011
4 2 "Buzz" 1-1-2011
5 2 "Fizz" 1-2-2011
6 2 "Beam" 1-3-2011
我该怎么做?
如果它只是一个独立的xml值,我可以这样做:
DECLARE @xml2 XML = '
<History>
<Node date="1-1-2011">World</Node>
<Node date="1-2-2011">Foo</Node>
<Node date="1-3-2011">Bar</Node>
</History>'
SELECT
x.value('(@date)[1]','date') AS [Date]
,x.value('.', 'nvarchar(50)') AS Value
FROM @xml2.nodes('/History/Node') temp(x)
但是当XML数据是表列的一部分时,我不知道该怎么做。我可能想办法用cursor
来强制执行它,但我想知道是否有更优雅的声明性解决方案,我不知道。
答案 0 :(得分:9)
使用交叉申请
declare @T table (Id int, Value nvarchar(50), History xml)
insert into @T values (1, 'Hello','
<History>
<Node date="1-1-2011">World</Node>
<Node date="1-2-2011">Foo</Node>
<Node date="1-3-2011">Bar</Node>
</History>')
insert into @T values (2, 'Baz','
<History>
<Node date="1-1-2011">Buzz</Node>
<Node date="1-2-2011">Fizz</Node>
<Node date="1-3-2011">Beam</Node>
</History>')
select
Id,
h.n.value('.', 'varchar(10)') as Value,
h.n.value('@date', 'varchar(10)') as Date
from @T
cross apply history.nodes('History/Node') h(n)