sql-server - 在插入 XML 字段之前过滤重复节点

标签 sql-server xml tsql

我正在使用 xml 字段以这种格式存储对书籍的建议:

<Books>
  <Book id="1" score="2" />
  <Book id="2" score="3" />
</Books>

有时我需要将建议添加到此 xml 中。这是通过以下语句完成的:

DECLARE @books XML;
SELECT @books = Suggestions.query('//books/book') 
FROM User
WHERE UserId = @UserId

UPDATE User
SET Suggestions.modify('insert sql:variable("@books") as first into (//books)[1]')
WHERE UserId = @UserId

如何确保我没有插入已经存在的节点(仅基于 id 属性)。

最佳答案

实现它的一种方法是创建仅包含新值的新 XML 变量。

数据:

CREATE TABLE #User(UserId INT, Suggestions XML, Name VARCHAR(100));

INSERT INTO #User(UserId, Suggestions, Name)
VALUES (1, 
       '<Books>
          <Book id="1" score="2" />
          <Book id="2" score="3" />
        </Books>'
        ,'John');

DECLARE @books XML =N'<Book id="1" score="2" />
                      <Book id="2" score="3" />
                      <Book id="3" score="4" />
                      <Book id="4" score="4" />';

查询:

DECLARE @UserId INT = 1;
       ,@only_new_books XML;

;WITH books AS
(
   SELECT id    = s.c.value('@id', 'INT'),
          score = s.c.value('@score', 'INT')
   FROM @books.nodes('/Book') AS s(c)
), suggestions AS
( 
  SELECT UserId, 
      id    = s.c.value('@id', 'INT'),
      score = s.c.value('@score', 'INT')
  FROM #User
  CROSS APPLY Suggestions.nodes('//Books/Book') AS s(c)
  WHERE UserId = @UserId
)
SELECT @only_new_books = (SELECT b.id AS '@id',
                                 b.score AS '@score'
                          FROM books b
                          LEFT JOIN suggestions s
                            ON b.id = s.id
                          WHERE s.id IS NULL
                          FOR XML PATH('Book'),TYPE
                          );

UPDATE #User
SET Suggestions.modify('insert sql:variable("@only_new_books") 
                        as first into (//Books)[1]')
WHERE UserId = @UserId;

SELECT * FROM #User;

LiveDemo

输出:

╔════════╦══════════════════════════════════════╦══════╗
║ UserId ║             Suggestions              ║ Name ║
╠════════╬══════════════════════════════════════╬══════╣
║      1 ║ <Books>                              ║ John ║    
║        ║    <Book id="3" score="4" />         ║      ║
║        ║    <Book id="4" score="4" />         ║      ║
║        ║    <Book id="1" score="2" />         ║      ║
║        ║    <Book id="2" score="3" />         ║      ║
║        ║ </Books>                             ║      ║
╚════════╩══════════════════════════════════════╩══════╝

关于sql-server - 在插入 XML 字段之前过滤重复节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35046529/

相关文章:

android - 从 xml 开始 Intent

c - xmlCopyNode (libxml2) 内存泄漏?

ios - 带有 XML 的 Boxee UDP 广播发现 API(远程)

sql-server - ALTER DATABASE 失败,因为无法在数据库 '<db_name>' 上放置锁。稍后再试

sql - 在 SQL Server 数据库中从一张表批量插入到另一张表

sql-server - SQL Server 2014 转换函数出现问题

c# - 让 SqlDataAdapter 和 SqlCommand 混淆

c# - 最佳登录做法

sql - 将 nvarchar 值 '%' 转换为数据类型 int 时转换失败

sql - where table.* <> table.* - 有没有办法做这样的事情?