选择记录时如何锁定表不返回任何数据

时间:2016-07-24 22:52:48

标签: sql sql-server sql-server-2014

考虑下表:

| id   | objId | fieldNumber |
|------|-------|-------------|
| 902  | 1     | 1           |
| 908  | 1     | 2           |
| 1007 | 1     | 3           |
| 1189 | 8     | 1           |
| 1233 | 12    | 1           |
| 1757 | 15    | 1           |

我想为不存在的对象输入新记录。让我们说objId:16。对于每个obj 16,字段编号必须增加1.看看obj:1。如你所见,它增加1.现在,如果两个或多个数据库连接试图在同一时间插入obj 16时间我会有两个obj 16与fieldNumber 1.这不可能发生。我必须保证字段编号不一样,必须增加一个。

所以我的解决方案是通过objid获取所有记录。如果至少有一条记录,则通过该objid锁定所有记录,然后插入包含下一个fieldNumber的记录。

或者,当我通过objid获取所有记录时。如果没有记录,那么我将锁定整个表,然后插入一个带有fieldNumber 1的记录。

我怎样才能锁定整张桌子?如果你有更好的想法,请告诉我吗?

2 个答案:

答案 0 :(得分:1)

如果您可以处理异常,那么最简单的方法可能是在(objid, fieldnumber)上添加唯一约束。

然后您可以运行查询,例如:

insert into t(objid, fieldnumber)
    select @objid, coalesce(max(fieldnumber) + 1, 1)
    from t
    where objid = @objid;

如果两个并发线程尝试运行查询,则唯一约束将失败 - 并且线程可以重新尝试。

您还可以使用SERIALIZABLE表提示(解释为here)。

答案 1 :(得分:0)

似乎objIdfieldNumber一起(应该)构成此表的主键。这样规范化约束将自动执行。我认为这是一个更清洁的'解。但是如果你不能放弃自动编程PK方案,那么戈登的解决方案是无与伦比的。