【问题标题】:SQL Server concurrent transaction issueSQL Server 并发事务问题
【发布时间】:2011-12-14 09:04:05
【问题描述】:

我有一个方法,它通过以下查询启动事务:

INSERT INTO order_item (item_no, order_id)
SELECT TOP " + Quantity + " item_no, @order_id 
FROM items where status = 'Unused'

一旦执行了第一个插入命令,我想更新在上一个命令中插入到order_item 中的items 表中的所有item_no

UPDATE items (select item_no from order_item where order_id = @order_id) 
SET status = 'Used'

我担心如果其他事务在现有事务运行时开始,他们可能会选择应该标记为“已使用”的套件编号,因为可能会提交第一个事务以标记为“已使用”的项目.

如果有人能就这个问题提供一些建议,我们将不胜感激。

谢谢!

【问题讨论】:

  • 您使用的是什么版本的 SQL Server?

标签: sql-server sql-server-2008 transactions


【解决方案1】:

使用一些可组合的 DML 将这一切合二为一?

INSERT INTO order_item (item_no, order_id)
SELECT 
    X.item_no, @order_id
FROM
    (
    MERGE INTO items AS tgt
    USING
      (SELECT TOP (@whatever) item_no
       FROM items
       WHERE status = 'Unused'
      ) AS src ON tgt.item_no = src.item_no
    WHEN MATCHED
      UPDATE SET status = 'Used'
      OUTPUT $action as action, item_no -- $action needed for more complex stuff
    ) AS X
-- WHERE action = 'UPDATE' -- needed for more complex stuff

【讨论】:

  • 嗨,感谢您提供可组合的 DML 解决方案。不过最后一个问题,在运行 DML 之前,我将在“订单”表中创建一个新的订单记录,该记录返回 DML 中使用的 order_id。 INSERT INTO orders (order_date, order_by) VALUES (@order_date, @order_by) SET @order_id = SCOPE_IDENTITY() 其他事务是否会读取类似的 order_id 以在可组合 DML 中使用?
  • @pothios:SCOPE_IDENTITY() 是安全的。对于不同的交易,它会有所不同,但对于任何单个交易都是正确的
【解决方案2】:

假设您使用的是支持OUTPUT clause(2005 或更高版本)的 SQL Server 版本,我将反转操作:

DECLARE @Items table (item_no int /* Or varchar?, Whatever suits */ not null)
DECLARE @Quantity int

SET @Quantity = 5 /* or however this gets set */

UPDATE TOP (@Quantity) items SET status = 'Used'
OUTPUT inserted.item_no INTO @Items (item_no)
WHERE status = 'Unused'

INSERT INTO order_item (item_no,order_id)
SELECT item_no,@order_id from @Items

这样一来,您的第一条语句(UPDATE)就是选择项目并将它们自动标记为不可用。

【讨论】:

  • 可以在没有@items 表变量的情况下执行此操作,并在输出子句中直接插入order_item。 +1
【解决方案3】:

如果我对您的问题的理解正确,那么您有一个物品清单,并且您有一个已订购物品的表格。

如果这是真的,我认为你应该重新考虑这种排序机制。我更喜欢像银行账户和交易这样的设计。您从帐户中借记并在同一数据库交易中的交易表中添加一个条目。我不太喜欢这种“未使用”的标志系统。

【讨论】:

  • 好吧,flag 实际上是 0 或 1,而不是“Used”/“Unused”。我必须使用这个模型,因为库存中的每个项目都是从 csv 上传的,我必须将它们标记为“已使用”以防止它们再次被使用。
猜你喜欢
  • 2011-09-26
  • 2014-10-17
  • 1970-01-01
  • 1970-01-01
  • 2015-06-30
  • 1970-01-01
  • 2018-02-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多