如何在SQL Server上使用XQuery修改xml子节点

时间:2017-02-07 09:30:42

标签: sql-server xml xpath xquery xquery-sql

对于xml字段(SQL Server),我需要根据源表和条件在每个子节点中添加一个节点。 这是我的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>。数字和名称的匹配项写在表@T

declare @T table (name varchar(20), number int)
insert @T values
('Alessandro', 24)
,('Francesco', 10)
,('Daniele', 16)

要更新我使用XMLDATA.modify的节点,我使用xpath条件选择正确的节点:

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)。其他2行@T将被忽略。我需要为每个number添加node。 这是最终的XMLDATA:

<row>
  <node>
    <name>Francesco</name>
  </node>
  <node>
    <name>Alessandro</name>
    <number>24</number>
  </node>
  <node>
    <name>Daniele</name>
  </node>
</row>

2 个答案:

答案 0 :(得分:1)

我使用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>

谢谢。

答案 1 :(得分:0)

如果您的真实生活数据与示例一样简单,则可以更轻松地找到解决方案:

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')

如果这不适合您,请提供更实际的样本数据!