选择MAX(字段)+1 FROM ...并发问题

时间:2009-10-28 22:14:21

标签: sql-server concurrency insert

您好我担心合作伙伴应用程序的并发性在最后几天导致CRUDS操作出现问题,特别是对于插入操作。所以我运行了SQL Profiler并注意他的insert语句不使用事务,他也在使用:

INSERT INTO TABLEA VALUES ( (SELECT MAX(NUMBERFIELD) +1 FROM TABLEA), ....);

如何避免使用MAX()+ 1生成主键?我建议使用自动增量或交易范围,但他不想要或者他可能不知道如何实现这一点,是否还有另一种方法可以带领这个?

使用SQL和C ++ 1.1

*这不是我的代码,但我可能会考虑向他展示这篇文章,因为我认为他必须考虑所有意见都是受欢迎的。 :)

2 个答案:

答案 0 :(得分:4)

如果您正确编码,您应该能够获得与IDENTITY解决方案相同的并发性。这不直观;你会认为锁定会降低并发性。但是我用几个不同的连接进行了几次测试,并且证明了自己MAX + 1技巧与IDENTITY完全相同。您可以在以下博客文章的第一部分中看到讨论:

https://sqlblog.org/2009/10/12/bad-habits-to-kick-making-assumptions-about-identity

无论如何这里是我推荐的语法(我真的不相信INSERT ... VALUES(SUBQUERY)模型,抱歉):

   DECLARE @NextID INT;

   BEGIN TRANSACTION;

   SELECT @NextID = COALESCE(MAX(NumberColumn), 0) + 1
       FROM dbo.TableA WITH (UPDLOCK);

   INSERT dbo.TableA SELECT @NextID;

   COMMIT TRANSACTION;

你必须想象错误处理部分(为简洁而省略),但我认为你会得到漂移。

当然不要把这些都用于福音。您需要使用数据和访问模式在硬件上运行测试,以确定此方法是否会损害并发性。这很可能就是那些“依赖”的答案之一。

答案 1 :(得分:3)

您是否考虑过制作主键列IDENTITY?它将使SQL Server自动为列生成值:

CREATE TABLE Test (
    Id int identity primary key not null
    -- ...
)