Добавление или замена атрибута XQuery в одной команде обновления SQL - PullRequest
4 голосов
/ 04 октября 2010

У меня есть таблица со столбцом XML, Я хочу обновить XML, чтобы вставить атрибут или изменить значение атрибута, если атрибут уже существует.

Скажем, начальный xml:

Вставка:

UPDATE Table 
set XmlCol.modify('insert attribute att {"1"} into /d[1]')

Изменение:

UPDATE Table
set XmlCol.modify('replace value of /d[1]/@att with "1"')

вставить не удастся, если атрибут уже существует, заменить не удастся, если атрибут не существует. Я пытался использовать «если», но я не думаю, что это может работать, там я получаю сообщение об ошибке: «XQuery [modify ()]: синтаксическая ошибка рядом с« атрибутом », ожидается« еще ».»

Если попытка

UPDATE Table 
set XmlCol.modify('if empty(/d[1]/@att) 
                   then insert attribute att {"1"} into /d[1]
                   else replace value of /d[1]/@att with "1"')

В настоящее время я выбираю xml в переменную, а затем изменяю его с помощью T-SQL, а затем обновляю столбец новым xml. Это требует от меня блокировки строки в транзакции и, вероятно, дороже для БД.

Ответы [ 2 ]

3 голосов
/ 10 октября 2012

Из того, что я могу сказать, вы не можете сделать это с одним утверждением.Вы можете использовать метод exist () , чтобы выполнить это с помощью двух операторов обновления.

DECLARE @TestTable TABLE
(
    Id int,
    XmlCol xml
);

INSERT INTO @TestTable (Id, XmlCol)
VALUES
    (1, '<d att="1" />'),
    (2, '<d />'),
    (3, '<d att="3" />');

SELECT * FROM @TestTable;

UPDATE @TestTable
SET XmlCol.modify('replace value of /d[1]/@att with "1"')
WHERE XmlCol.exist('(/d[1])[not(empty(@att))]') = 1;

UPDATE @TestTable
SET XmlCol.modify('insert attribute att {"1"} into /d[1]')
WHERE XmlCol.exist('(/d[1])[empty(@att)]') = 1;

SELECT * FROM @TestTable;

Результат окончательного выбора:

Id          XmlCol
----------- -------------------
1           <d att="1" />
2           <d att="1" />
3           <d att="1" />
1 голос
/ 10 февраля 2017

Есть немного лучший способ, чем у Томмиса:

DECLARE @TestTable TABLE
(
    Id int,
    XmlCol xml
);

INSERT INTO @TestTable (Id, XmlCol)
VALUES
    (1, '<UserSettings> </UserSettings>'),
    (2, '<UserSettings><timeout>3</timeout> </UserSettings>'),
    (3, '<UserSettings> </UserSettings>');

UPDATE @TestTable
SET XmlCol.modify('replace value of (/UserSettings/timeout/text())[1] with "1"')
WHERE Id = 3 and XmlCol.exist('/UserSettings/timeout') = 1;
IF @@ROWCOUNT=0
    UPDATE @TestTable
    SET XmlCol.modify('insert <timeout>5</timeout> into (/UserSettings)[1] ')
    WHERE Id = 3;

SELECT * FROM @TestTable;

Решение представляет собой комбинацию Tommys и простого SQL и требует только 1 SQL UPDATE, если столбец существует. Томмис всегда получает два обновления.

...