我有一个表A(SQL Server 2008),其中包含一组最小和最大数字。在我的一个存储过程中,我使用此表与产品表B连接,以查找介于最小和最大之间的可用产品编号,然后插入具有此产品编号的新产品。所以我想要下一个最小/最大的免费号码。
在查找下一个可用号码和插入产品行之间,我想要一个锁,以防止任何人找到相同的号码(并给予重复)。
在这种情况下我该怎么想?我是否应该在A表上获得更新锁,即使我从未修改它?在我插入表B并且事务结束后应该释放锁?此更新锁是否会阻止其他事务读取表A?
编辑:最小/最大表是不同产品系列的表。根据您想要的哪个系列,我想尝试在此序列中找到可用的数字。 productnr并不是唯一的,但是可以将它与第二列结合使用。简化sp:
CREATE PROCEDURE [dbo].[InsertProduct]
(
@Param1 int,
@Param2 bit,
...
@Param20 int) AS
BEGIN
DECLARE @ProductNr int
--Here I do a query to determine which ProductNr I should have. Checking that the number is between max/min in the series and that no other product has this productnr.
--Now insert the row
INSERT INTO Products VALUES (@Param1, @ProductNr, ...., @Param2
END
答案 0 :(得分:1)
只需将下一个数字插入表B.如果提交,则由您自己使用。如果您收到密钥违规,则表示其他流程刚刚输入新号码。在这种情况下,请递增新号码,然后重试。
数据库会自动为您处理这种情况。无需手动锁定。
答案 1 :(得分:1)
您的问题有点模糊,如果您包含一些示例数据会有所帮助。
无论如何,我过去使用的一种策略是尝试用一个语句包装所有内容 - 在这里,它将是一个INSERT。每个SQL语句都事实上包装在它自己的隐式事务中(原子性,关系数据库属性的ACID中的“A”代表)。在伪代码中,它看起来像:
INSERT MyTable (Id, Plus, Other, Columns)
select CalcForNewId, Plus, Other, Columns
from [what may be a pertty convoluted query to determine the "next" valid Id]
这只有在您可以将业务逻辑编写为单个合理查询时才有效(其中“合理”意味着它不会在当前或任何其他用户锁定,阻塞或死锁一段不合理的时间)。这可能是一个非常高的顺序,但我会考虑到必须编写复杂的BEGIN TRANSACTION / COMMIT / ROLLBACK代码,并且每天都会混合使用TRY ... CATCH块。 (这当然会奏效,而且我也相应地赞成了@Scott Bruns。)