SQL存储过程同时调用问题

时间:2017-05-09 21:27:56

标签: sql sql-server tsql stored-procedures

我在sql server 2008中存储过程,我的存储过程计算并从表B的列中获取最后一个数字“not primary key”,并在此数字上添加一个(+1)以在下一个语句中使用它相同的存储过程。

我的问题是我有一些重复的数字,我认为这发生在多个用户同时调用存储过程时。这是问题,我该如何解决?

我的代码如下: -

DECLARE @ID AS NVARCHAR(10)
SET @ID =   (
                SELECT TOP 1 MyNo
                FROM Employee
                WHERE (
                            (TypeID = @TypeID) AND
                            (Year = @Year)
                      )
                ORDER BY ID DESC
            )

SET @ID = ISNULL(@ID,0) + 1


INSERT INTO Employee (name,lname,MyNo) VALUES (@name,@lname,@MyNo)

2 个答案:

答案 0 :(得分:1)

您可以使用WITH(TABLOCKX,HOLDLOCK)语法在事务持续时间内锁定表:

BEGIN TRANSACTION
DECLARE @ID AS NVARCHAR(10)
SET @ID =   (
                SELECT TOP 1 MyNo
                FROM Employee WITH (TABLOCKX, HOLDLOCK)
                WHERE (
                            (TypeID = @TypeID) AND
                            (Year = @Year)
                      )
                ORDER BY ID DESC
            )

SET @ID = ISNULL(@ID,0) + 1


INSERT INTO Employee (name,lname,MyNo) VALUES (@name,@lname,@MyNo)
COMMIT TRANSACTION

您可以在此处找到有关TABLOCK和TABLOCKX的更多信息: https://docs.microsoft.com/en-us/sql/t-sql/queries/hints-transact-sql-table

根据讨论,在这种情况下使用的最佳锁定是:

(UPDLOCK,HOLDLOCK)

答案 1 :(得分:1)

如果您不能使用Identity列或表锁,则另一种方法是使用sp_getapplock

这种机制的优点是,这种锁可用于多个不应同时运行的存储过程,也可用于跨多个表的操作。如果锁定不可用,它还允许处理超时和其他类型的行为。

使用此功能时必须小心,确保正确获取和释放锁定,否则会产生比解决方案更多的问题。