【问题标题】:XQuery adding or replacing attribute in single SQL update commandXQuery 在单个 SQL 更新命令中添加或替换属性
【发布时间】:2011-04-20 17:42:59
【问题描述】:

我有一个带有 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"')

如果属性已经存在,则插入将失败,如果该属性不存在,则替换将失败。 我曾尝试使用 'if',但我认为它不起作用,出现错误:“XQuery [modify()]: Syntax error near 'attribute', expected '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 更新列,这需要我将行锁定在事务中,并且对于数据库来说可能更昂贵。

【问题讨论】:

    标签: sql-server xml tsql xquery xquery-sql


    【解决方案1】:

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

    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" />
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-12-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-12
        • 2018-03-25
        相关资源
        最近更新 更多