繁体   English   中英

如果根据三列与最新版本的记录不匹配,是否可以在 SQL Server 中插入记录?

[英]Is there a way to insert a record in SQL server if it does not match the latest version of the record based on three of the columns?

考虑以下名为UserAttributes表:

+----+--------+----------+-----------+
| Id | UserId | AttrName | AttrValue |
+----+--------+----------+-----------+
|  4 |      1 | FavFood  | Apples    |
|  3 |      2 | FavFood  | Burgers   |
|  2 |      1 | FavShape | Circle    |
|  1 |      1 | FavFood  | Chicken   |
+----+--------+----------+-----------+

如果用户的特定属性的最新版本具有与最新版本不匹配的值,我想在此表中插入一条新记录。

我的意思是,例如,如果我要这样做: SELECT TOP(1) * FROM [UserAttributes] WHERE [UserId] = 1 AND [AttrName] = 'FavFood' ORDER BY [Id] DESC

我将能够看到用户 ID 1 当前最喜欢的食物是“苹果”。

是否有一个安全的并发查询,如果它与该用户当前最喜欢的食物不匹配,它只会插入一个新的最喜欢的食物?

我尝试将MERGE查询与HOLDLOCK一起使用,但问题是WHEN MATCHED / WHEN NOT MATCHED ,如果我不想在用户之前将他们最喜欢的食物(在本例中)设置为新值。 然而,它没有考虑到用户可能会切换到新的最喜欢的食物,然后又改回他们以前最喜欢的食物。 我想保留所有更改作为历史记录。

在上面的数据集中,如果用户 ID 1 的新喜欢的食物是“汉堡”,我想插入一条新记录,但如果他们新喜欢的食物是“苹果”,我不想插入记录(因为那是他们的目前最喜欢的食物)。 我还想让这个操作对于并发是安全的。

感谢您的帮助!

编辑:我可能还应该提到,当我将此操作拆分为两个查询时(即:首先选择他们当前最喜欢的食物,然后仅在检测到新食物时才执行插入查询)它在正常条件下工作。 但是,我们正在观察竞争条件(因此会出现重复),因为(您可能已经猜到)上面的数据集只是一个示例,并且有许多线程同时在该表上运行。

有点难看,但要在一个命令中完成,您可以插入用户(新的)最喜欢的食物,但使用他们当前值的EXCEPT进行过滤。

例如,(假设用户的新数据在@UserID、@FavFood

; WITH LatestFavFood AS
    (SELECT TOP(1) UserID, AttrName, AttrValue 
      FROM  [UserAttributes] 
      WHERE [UserId] = @UserID AND [AttrName] = 'FavFood' 
      ORDER BY [Id] DESC
     )
INSERT INTO UserAttributes (UserID, AttrName, AttrValue)
    SELECT  @UserID, 'FavFood', @FavFood
  EXCEPT
    SELECT  UserID, AttrName, AttrValue
    FROM    LatestFavFood

这是一个运行了 3 次的DB_Fiddle

编辑:我已将上述更改为假设 AttrName 而不是 nvarchar 的 varchar 类型。 小提琴有混合物。 确保您正确理解它们会很好(尤其是食物,因为它可能具有特殊字符)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM