4

我有一个带有 XML 列的表,如果属性已经存在,我想更新 xml 以插入属性或更改属性值。

假设起始 xml 是:< d />

插入:

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

如果该属性已存在,则插入将失败,如果该属性不存在,则替换将失败。我曾尝试使用'if',但我认为它不起作用,出现错误:“XQuery [modify()]: 'attribute' 附近的语法错误,预期为'else'。”

如果尝试

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 更新列,这需要我将行锁定在事务中,并且对于数据库来说可能更昂贵。

4

2 回答 2

4

据我所知,你不能用单一的语句来做到这一点。您可以使用exists() 方法通过两个更新语句来完成此操作。

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" />
于 2012-10-10T19:25:52.710 回答
1

有一个比 Tommys 稍微好一点的方法:

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。Tommys 总是需要两次更新。

于 2017-02-10T07:38:57.683 回答