如何在 SQL 服务器上使用 XQuery 修改 xml 子节点
How to modify xml subnodes with XQuery on SQL Server
对于 xml 字段(SQL 服务器),我需要根据源 table 和条件在每个子节点中添加一个节点。
这是我的 xml 数据:
declare @X table (XMLDATA xml)
insert @X values('
<row>
<node>
<name>Francesco</name>
</name>
<node>
<label>Alessandro</name>
</node>
<node>
<name>Daniele</name>
</node>
</row>')
对于每个 <name>
,我想添加一个节点 <number>
。数字和名字的匹配写成 table @T
:
declare @T table (name varchar(20), number int)
insert @T values
('Alessandro', 24)
,('Francesco', 10)
,('Daniele', 16)
要更新我使用 XMLDATA.modify
的节点,我使用 xpath 条件 select 正确的节点:
update @X set XMLDATA.modify('insert element number {sql:column("number")} as last into (row/node[name=sql:column("name")])[1]')
from @X
cross join @T
上面的查询仅适用于 @T
的第一行(示例中为 Alessandro/24)。 @T
的其他 2 行将被忽略。我需要将 number
添加到每个 node
。
这是最终的 XMLDATA:
<row>
<node>
<name>Francesco</name>
</node>
<node>
<name>Alessandro</name>
<number>24</number>
</node>
<node>
<name>Daniele</name>
</node>
</row>
我使用 while 循环。请检查下面的代码,它可能对你有帮助。
declare @X table (XMLDATA xml)
insert @X values('
<row>
<node>
<name>Alessandro</name>
</node>
<node>
<name>Francesco</name>
</node>
<node>
<name>Daniele</name>
</node>
</row>')
declare @T table (name1 varchar(20), number int,RowID int identity(1,1) not null)
insert @T values
('Alessandro', 24)
,('Francesco', 10)
,('Daniele', 16)
DECLARE @i int,@iCount int,@namevalue varchar(100)='',@number int
SET @i = 1
SELECT @iCount=MAX(RowID) FROM @T
WHILE (@i <= @iCount)
BEGIN
SELECT @namevalue=name1 FROM @T WHERE RowID=@i
SELECT @number=number FROM @T WHERE RowID=@i
update @X set XMLDATA.modify('insert element number {sql:variable("@number")} as last into (row/node)[name=sql:variable("@namevalue")][1]')
from @X
cross join @T
SET @i = @i + 1
END
SELECT * FROM @X
输出:
<row>
<node>
<name>Alessandro</name>
<number>24</number>
</node>
<node>
<name>Francesco</name>
<number>10</number>
</node>
<node>
<name>Daniele</name>
<number>16</number>
</node>
</row>
谢谢。
如果您的现实生活中的数据像示例一样简单,则可以更容易地找到解决方案:
declare @X table (XMLDATA xml)
insert @X values(
'<row>
<node>
<name>Francesco</name>
</node>
<node>
<name>Alessandro</name>
</node>
<node>
<name>Daniele</name>
</node>
</row>')
declare @T table (name varchar(20), number int)
insert @T values
('Alessandro', 24)
,('Francesco', 10)
,('Daniele', 16);
SELECT nm.value(N'.','nvarchar(max)') AS name
,t.number
FROM @X
CROSS APPLY XMLDATA.nodes(N'/row/node/name') AS A(nm)
INNER JOIN @T AS t ON t.name=nm.value(N'.','nvarchar(max)')
FOR XML PATH('node'),ROOT('row')
如果这对您不起作用,请提供更真实的示例数据!
对于 xml 字段(SQL 服务器),我需要根据源 table 和条件在每个子节点中添加一个节点。 这是我的 xml 数据:
declare @X table (XMLDATA xml)
insert @X values('
<row>
<node>
<name>Francesco</name>
</name>
<node>
<label>Alessandro</name>
</node>
<node>
<name>Daniele</name>
</node>
</row>')
对于每个 <name>
,我想添加一个节点 <number>
。数字和名字的匹配写成 table @T
:
declare @T table (name varchar(20), number int)
insert @T values
('Alessandro', 24)
,('Francesco', 10)
,('Daniele', 16)
要更新我使用 XMLDATA.modify
的节点,我使用 xpath 条件 select 正确的节点:
update @X set XMLDATA.modify('insert element number {sql:column("number")} as last into (row/node[name=sql:column("name")])[1]')
from @X
cross join @T
上面的查询仅适用于 @T
的第一行(示例中为 Alessandro/24)。 @T
的其他 2 行将被忽略。我需要将 number
添加到每个 node
。
这是最终的 XMLDATA:
<row>
<node>
<name>Francesco</name>
</node>
<node>
<name>Alessandro</name>
<number>24</number>
</node>
<node>
<name>Daniele</name>
</node>
</row>
我使用 while 循环。请检查下面的代码,它可能对你有帮助。
declare @X table (XMLDATA xml)
insert @X values('
<row>
<node>
<name>Alessandro</name>
</node>
<node>
<name>Francesco</name>
</node>
<node>
<name>Daniele</name>
</node>
</row>')
declare @T table (name1 varchar(20), number int,RowID int identity(1,1) not null)
insert @T values
('Alessandro', 24)
,('Francesco', 10)
,('Daniele', 16)
DECLARE @i int,@iCount int,@namevalue varchar(100)='',@number int
SET @i = 1
SELECT @iCount=MAX(RowID) FROM @T
WHILE (@i <= @iCount)
BEGIN
SELECT @namevalue=name1 FROM @T WHERE RowID=@i
SELECT @number=number FROM @T WHERE RowID=@i
update @X set XMLDATA.modify('insert element number {sql:variable("@number")} as last into (row/node)[name=sql:variable("@namevalue")][1]')
from @X
cross join @T
SET @i = @i + 1
END
SELECT * FROM @X
输出:
<row>
<node>
<name>Alessandro</name>
<number>24</number>
</node>
<node>
<name>Francesco</name>
<number>10</number>
</node>
<node>
<name>Daniele</name>
<number>16</number>
</node>
</row>
谢谢。
如果您的现实生活中的数据像示例一样简单,则可以更容易地找到解决方案:
declare @X table (XMLDATA xml)
insert @X values(
'<row>
<node>
<name>Francesco</name>
</node>
<node>
<name>Alessandro</name>
</node>
<node>
<name>Daniele</name>
</node>
</row>')
declare @T table (name varchar(20), number int)
insert @T values
('Alessandro', 24)
,('Francesco', 10)
,('Daniele', 16);
SELECT nm.value(N'.','nvarchar(max)') AS name
,t.number
FROM @X
CROSS APPLY XMLDATA.nodes(N'/row/node/name') AS A(nm)
INNER JOIN @T AS t ON t.name=nm.value(N'.','nvarchar(max)')
FOR XML PATH('node'),ROOT('row')
如果这对您不起作用,请提供更真实的示例数据!