Из тега [tsql] и данного примера я предполагаю, что это SQL -Server. Пожалуйста, не забудьте пометить свой следующий вопрос соответствующим образом (продукт и версия).
Очень ограниченная функция .modify()
допускает одно единственное изменение на вызов.
Лучший подход во многом зависит по фактической проблеме ...
Вы можете пройти по маршруту FLWOR :
Сначала я объявляю таблицу макетов с тремя строками. Одна строка - ваш образец, одна строка уже содержит один Zip, а третья - ZIP в обоих XML фрагментах.
Declare @mockupTable TABLE(ID INT IDENTITY, SomeDescription VARCHAR(100), YourXml XML);
INSERT INTO @mockupTable VALUES
('Your sample, no Zip codes',
'<DataObject>
<Objects>
<Object Name="FirstName" Value="John" />
<Object Name="LastName" Value="Smith" />
<Object Name="City" Value="Miami" />
<Object Name="State" Value="FL" />
<Object Name="Department" Value="HR" />
</Objects>
</DataObject>
<DataObject>
<Objects>
<Object Name="FirstName" Value="Jane" />
<Object Name="LastName" Value="Doe" />
<Object Name="City" Value="Hollywood" />
<Object Name="State" Value="FL" />
<Object Name="Department" Value="Accounting" />
</Objects>
</DataObject>')
,('One has a zip code already',
'<DataObject>
<Objects>
<Object Name="FirstName" Value="John" />
<Object Name="LastName" Value="Smith" />
<Object Name="City" Value="Miami" />
<Object Name="State" Value="FL" />
<Object Name="Zip" Value="12345" />
<Object Name="Department" Value="HR" />
</Objects>
</DataObject>
<DataObject>
<Objects>
<Object Name="FirstName" Value="Jane" />
<Object Name="LastName" Value="Doe" />
<Object Name="City" Value="Hollywood" />
<Object Name="State" Value="FL" />
<Object Name="Department" Value="Accounting" />
</Objects>
</DataObject>')
,('Both have zip codes',
'<DataObject>
<Objects>
<Object Name="FirstName" Value="John" />
<Object Name="LastName" Value="Smith" />
<Object Name="City" Value="Miami" />
<Object Name="State" Value="FL" />
<Object Name="Zip" Value="12345" />
<Object Name="Department" Value="HR" />
</Objects>
</DataObject>
<DataObject>
<Objects>
<Object Name="FirstName" Value="Jane" />
<Object Name="LastName" Value="Doe" />
<Object Name="City" Value="Hollywood" />
<Object Name="State" Value="FL" />
<Object Name="Zip" Value="12345" />
<Object Name="Department" Value="Accounting" />
</Objects>
</DataObject>');
- это запрос
SELECT t.*
,t.YourXml.query
('
for $os in /DataObject/Objects
return
<DataObject>
<Objects>
{
for $o in $os/Object
return
if(empty($os[Object[@Name="Zip"]]) and $o[@Name="State"]) then
($o,<Object Name="Zip" Value="abcde"/>)
else
$o
}
</Objects>
</DataObject>
')
FROM @mockupTable t;
Идея вкратце:
Мы перебираем все <Objects>
, используя переменную $os
.
Теперь мы начинаем секунду для -l oop ниже $os
и перебираем все содержащиеся <Object>
elements.
Идея такова: если $os
НЕ получил <Object>
с Name
равным Zip
(см. использование empty()
) и текущий <Object>
имеет Name
of State
мы собираемся вернуть элемент $o
без изменений, но вместе с новым элементом для вставки Zip
-элемента сразу после элемента с «State».
В любом другом случае мы просто возвращаем $o
, возвращая, таким образом, все как есть .
Вы можете использовать созданное XML в простом ОБНОВЛЕНИИ и обновлять вашу таблицу одним вызовом.
ОБНОВЛЕНИЕ
Код для обновления всей таблицы за один звонок
WITH updatableCTE AS
(
SELECT t.YourXml
,t.YourXml.query
('
for $os in /DataObject/Objects
return
<DataObject>
<Objects>
{
for $o in $os/Object
return
if(empty($os[Object[@Name="Zip"]]) and $o[@Name="State"]) then
($o,<Object Name="Zip" Value="abcde"/>)
else
$o
}
</Objects>
</DataObject>
') AS NewContent
FROM @mockupTable t
)
UPDATE updatableCTE SET YourXml=NewContent;
--check the result
SELECT * FROM @mockupTable