我使用以下查询来获取未使用代码的数量--AvailableCodes表中不在Usage表中的代码:

SELECT code, type
FROM
(
  SELECT avc.code, avc.type,
         COUNT(CASE WHEN avc.type = 'type_1' THEN 1 END) OVER () cn1,
         COUNT(CASE WHEN avc.type = 'type_3' THEN 1 END) OVER () cn2,
         ROW_NUMBER() OVER (PARTITION BY avc.type ORDER BY avc.id) rn
  FROM  AvailableCodes avc left JOIN Usage usg
  ON usg.code = avc.code
  WHERE usg.code IS NULL
) t
WHERE (cn1 >= 2 AND cn2 >= 1) AND
      ((type = 'type_1' AND rn <= 2) OR (type = 'type_3' AND rn <= 1))
ORDER BY type, code

我希望锁定读取选定的行,但允许读取其他代码,以防多个用户同时try 访问此代码.

但我不确定将锁定部分放在哪里,with(rowlock, updlock, holdlock)的方式将仅锁定AvailableCodes中选定的行以供读取,但允许读取其他行.

Update:更清楚地说,我真正需要做的是: 在上面的查询之后,我得到了一个需要插入到Usage表中的代码数组,例如:['111', '222', '1232'].

然后我需要将它们插入到Usage,这样其他用户就不会再次使用这些代码. 在上面的查询之后,我在同一查询中批量插入了它们.

Update 2:

我正在try 实现的是一个系统,用户可以在其中 Select 每种类型的折扣代码数量.例如,他们想要type_1中的5个代码,type_2中的3个代码,type_3中的10个代码.

并且每个代码不应该被多次使用.

因此,我的查询批量 Select 可用的代码并将其批量插入

推荐答案

100

您的INSERT查询需要HOLDLOCK, UPDLOCK,以确保锁定预期行的"空".

目前还不清楚您想要插入什么逻辑,但您可以在一条语句中完成此操作,不需要显式事务,只需一个锁定提示即可.

INSERT Usage (code)
SELECT code
FROM
(
  SELECT avc.code, avc.type,
         COUNT(CASE WHEN avc.type = 'type_1' THEN 1 END) OVER () cn1,
         COUNT(CASE WHEN avc.type = 'type_3' THEN 1 END) OVER () cn2,
         ROW_NUMBER() OVER (PARTITION BY avc.type ORDER BY avc.id) rn
  FROM  AvailableCodes avc
  WHERE NOT EXISTS (SELECT 1
      FROM Usage usg WITH (HOLDLOCK, UPDLOCK)
      WHERE usg.code = avc.code
  )
) t
WHERE (cn1 >= 2 AND cn2 >= 1) AND
      ((type = 'type_1' AND rn <= 2) OR (type = 'type_3' AND rn = 1))
;

您还可以为整个语句设置隔离级别,而不是HOLDLOCK锁定提示.不过,你仍然需要UPDLOCK.

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

请注意,这将导致所有表引用具有相同的隔离级别.

Sql相关问答推荐

如何查询未命名对象的SON数组

PG SQL中按条件聚合值

如何实现一个广泛的多级自连接PostgreSQL查询?

使用交叉应用透视表在SQL中转换分段时间段&

如何更改函数返回的列名?

SQL查询:合并2个表

Postgres,使用iLike运算符从json数组中搜索的工作方式与从常规表中搜索不同

基于多个字段删除Access中的重复记录,同时保留最低优先级

在Postgres中实现合并功能的干净方法,因为当目标/源不匹配时

如何在不更改S代码的情况下,判断存储过程调用了多少次clr函数?

收到%1、%2或%2邮箱的唯一客户

如何隐藏聚合JSON数组元素的键

从列中提取子字符串的ORDER BY CASE语句

每小时 Select 1行

按行值出现的顺序对行值进行分组

递归 CTE 附加为行

在没有订单的情况下,如何生成一个值为0的顾客天数行

复制SQL Server临时表

根据行号将列转置为没有任何id或键列的行

在 PostgreSQL 中使用重音敏感排序进行重音不敏感搜索