Обновить значение узла XML T-SQL на основе значения другого узла на том же уровне - PullRequest
2 голосов
/ 11 июня 2019

Я хотел бы обновить кусок 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 ]

1 голос
/ 11 июня 2019

Попробуйте вот так

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() может изменить только одно место на вызов.Это означает, что первый аргумент (XPath после replace value of) должен быть одиночным.Нам нужна вторая переменная, чтобы определить, какой параметр мы хотим изменить.Здесь я использую:

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

Вы можете прочитать это как Погружение в <ParameterValues>, затем в <ParameterValue> и найти тот с данным Именем.Ниже мы погрузимся в <Value> и вернем text().

Если будет несколько случаев, мы выберем первое в любом случае и заменим его на заданное значение.

1 голос
/ 11 июня 2019

См. Следующий фрагмент:

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

Хитрость заключается в применении условия в квадратных скобках.

...