仅当总计数小于阈值时,才将行插入SQL Server表

时间:2014-10-19 08:19:58

标签: sql sql-server tsql

我正在使用SQL Server 2012.

我有用于存储用户的表。允许的最大用户数为100万。我有一个我正在注册用户的sproc。当我插入时,我想确保users表中的总行数不超过100万。我更愿意使用一种允许最大并发的方法。

我相信我可以使用具有SERIALIZABLE的ISOLATION LEVEL的事务,然后首先计算行数并在总计数小于1百万时插入。我的理解是SERIALIZABLE是非常严格的,并且随着并发性的增加会导致性能下降。

IF(SELECT COUNT(*) FROM Users) < 100000
BEGIN
    INSERT INTO Users VALUES (@Name, @Email, @Password)
END

如何以原子方式执行此操作以确保总行数少于100万,但同时我执行最小锁定以防止阻止其他事务?

针对这种情况的任何解决方案/最佳做法?

1 个答案:

答案 0 :(得分:6)

您可以创建SELECT来检查用户数量并检索新用户的数据,并使用该选项插入表格中:

INSERT INTO users (
  name, email, [password]
)
SELECT
  'newUser' AS name
  , 'email@example.com' AS email
  , 'fsfsfs' AS [password]
FROM
  users
HAVING
  COUNT(*) < 100000;

当数据库中的用户少于100000时,SELECT语句将返回一行,当有100000个或更多用户时,将返回0记录。

整个语句(INSERT..SELECT)在每种情况下都有效,但当SELECT部分返回0行时,INSERT将不会插入任何内容。

使用SERIALIZABLE事务级别,可以保证concurent写入不会相互干扰。 COUNT(*)使用最有效的索引/键来计算行数,这意味着锁定时间将是最小的。

由于整个操作在一个语句中完成,因此可以防止在执行SELECTINSERT之间插入

SQL Fiddle demo