基于同一级别上其他节点的值更新节点值XML T-SQL

时间:2019-06-11 11:39:28

标签: sql-server xml tsql xquery-sql

我想更新一个保存在变量中的xml。我想更新Value的值,其中Name是给定值。这是xml的模型:

<ParameterValues>
  <ParameterValue>
    <Name>TO</Name>
    <Value>me@you.com</Value>
  </ParameterValue>
  <ParameterValue>
    <Name>CC</Name>
    <Value>bob@email.com</Value>
  </ParameterValue>
  <ParameterValue>
    <Name>Priority</Name>
    <Value>NORMAL</Value>
  </ParameterValue>
</ParameterValues>

我写了下面的内容,该内容总是更新第一个值,但是我想更改modify命令,以便与where子句等效-我想更新(例如)同一节点中Name = "CC"的值。我该如何实现?

我在网上看到的所有示例都假定我对树结构中的每个节点都有一个唯一的标识符,该标识符高于我要更新的值,而不是在同一级别。

DECLARE @Email VARCHAR(50) = 'New@email.co.uk';
DECLARE @Ext XML =
'<ParameterValues>
  <ParameterValue>
    <Name>TO</Name>
    <Value>me@you.com</Value>
  </ParameterValue>
  <ParameterValue>
    <Name>CC</Name>
    <Value>bob@email.com</Value>
  </ParameterValue>
  <ParameterValue>
    <Name>Priority</Name>
    <Value>NORMAL</Value>
  </ParameterValue>
</ParameterValues>';

SET @Ext.modify('replace value of (//Value/text())[1] with sql:variable("@Email")');

SELECT
     Col.value('./Name[1]','VARCHAR(100)')  AS [Name]
    ,Col.value('./Value[1]','VARCHAR(1000)')AS [Value]
FROM
    @Ext.nodes('//ParameterValue')  AS Tab(Col);

感谢所有帮助!

2 个答案:

答案 0 :(得分:1)

请参见以下代码段:

SET @Ext.modify('replace value of (//Value[../Name="CC"]/text())[1] with sql:variable("@Email")');

诀窍是在方括号中加上条件。

答案 1 :(得分:1)

尝试一下

DECLARE @Ext XML =
'<ParameterValues>
  <ParameterValue>
    <Name>TO</Name>
    <Value>me@you.com</Value>
  </ParameterValue>
  <ParameterValue>
    <Name>CC</Name>
    <Value>bob@email.com</Value>
  </ParameterValue>
  <ParameterValue>
    <Name>Priority</Name>
    <Value>NORMAL</Value>
  </ParameterValue>
</ParameterValues>';

DECLARE @Email VARCHAR(50) = 'New@email.co.uk';
DECLARE @SearchFor VARCHAR(100)='CC'

SET @Ext.modify('replace value of (/ParameterValues/ParameterValue[Name=sql:variable("@Searchfor")]/Value/text())[1] with sql:variable("@Email")');

SELECT @Ext;

简而言之。

.modify()方法每次呼叫只能更改一个位置。这意味着第一个参数(replace value of之后的XPath)必须是单例。我们需要第二个变量来定义我们要更改的参数。我在这里使用:

replace value of (/ParameterValues
                 /ParameterValue[Name=sql:variable("@Searchfor")]
                 /Value/text())[1] 
with sql:variable("@Email")

您可以将其读为进入<ParameterValues>,然后进入<ParameterValue>并找到具有给定名称的一个。在下面,我们进入<Value>,然后返回text()

如果有多次出现,我们将在任何情况下都选择第一个,并将其替换为给定值。