我将以下XML文档存储在具有XML
类型的TSQL变量中:
<root>
<parent>
<child>Alice</child>
<child>Bob</child>
<child>Carol</child>
</parent>
<house>
<room><id>1</id></room>
<room><id>2</id></room>
<room><id>3</id></room>
</house>
</root>
我想迭代&#34;堂兄&#34;节点(即父节点为兄弟节点的节点)并在表中插入每行迭代一行,每个表兄插入一列。所以结果会是这样的:
Child | Room
------------
Alice | 1
Bob | 2
Carol | 3
(我知道有一个与孩子一样多的房间。)
我觉得这是一项简单的任务,但似乎无法找到方法。我是SQL Server和XPath的初学者,可能缺乏查找文档的术语。
我到目前为止尝试的是迭代,比如child
元素,并尝试使用room
从那里读取匹配的ROW_NUMBER
元素来挑选房间我想要:
INSERT INTO children (child, room)
SELECT
child = T.Item.value('(../parent/child/text())[' + (ROW_NUMBER() OVER(ORDER BY T.Item)) + ']', 'VARCHAR(10)'),
room = T.Item.value('(id/text())[1]', 'CHAR(1)')
FROM
@XML.nodes('root/house/room') AS T(Item)
但是SQL服务器抱怨value()
只接受字符串文字作为第一个参数(那是什么限制?)。
我知道如何才能做到这一点吗?
答案 0 :(得分:5)
不确定这是最佳还是最短路,但它会产生您需要的输出:
DECLARE @x XML='
<root>
<parent>
<child>Alice</child>
<child>Bob</child>
<child>Carol</child>
</parent>
<house>
<room><id>1</id></room>
<room><id>2</id></room>
<room><id>3</id></room>
</house>
</root>';
;WITH childs AS (
SELECT
n.e.value('.','NVARCHAR(128)') AS child,
id=ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM
@x.nodes('/root/parent/child') AS n(e)
),
room_ids AS (
SELECT
n.e.value('.','NVARCHAR(128)') AS room_id,
id=ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM
@x.nodes('/root/house/room/id') AS n(e)
)
SELECT
c.child,
r.room_id
FROM
childs AS c
INNER JOIN room_ids AS r ON
r.id=c.id
ORDER BY
c.id;
答案 1 :(得分:3)
作为纯XPath查询,您可以这样做:
SELECT The.Room.value('id[1]','varchar(max)'),The.Room.value('let $r:=. return (../../parent/child[position()=$r]/text())[1]','varchar(max)')
FROM @YourXML.nodes('/root/house/room') AS The(Room)
但是 - 说实话 - 我更喜欢TT。的解决方案。该解决方案依赖于房间从1到n编号而没有间隙。即使是未分类的房间号码,TT。的解决方案也能正常工作......