【问题标题】:Setting ownership in a transaction SQL [duplicate]在事务 SQL 中设置所有权 [重复]
【发布时间】:2014-03-18 06:08:03
【问题描述】:

这几天一直困扰着我,我有一个自动增量的表,我想要的是增量值的值将插入同一行。问题是并发用户访问查询时,不会复制正确的值。

下面是我的桌子:

CREATE TABLE tblTransactions
  (
     dctransno     INT IDENTITY PRIMARY KEY,
     vcDescription VARCHAR,
     dcTransNoCopy INT NULL,
     user          VARCHAR        
  )

和我的查询:

BEGIN TRAN

INSERT INTO tblTransactions
            (dctransno,
             user)
VALUES      (@vcDescription,
             @user); 

SET @identity = @@IDENTITY -- get the identity

UPDATE tblTransactions
SET    dcTransNoCopy = @identity
WHERE  dcTransNo = @identity
       AND user = @user; -- insert

COMMIT TRAN 

我想要实现的是我可以像下面的示例那样进行分组交易。问题是我上面的查询没有所有权。假设 userA 和 userB 同时使用系统:

       dcTransNo      Description     dcTransNoCopy      User
          1          Transaction1      1                userA
          2          Transaction2      1                userA
          3          Transaction3      1                userA
          4          Transaction1      3                userB       ---> not correct, ClonetransNo value for userB should be 4 not 3.

请帮忙,提前谢谢。

【问题讨论】:

  • 我假设 dcTransNoCopy 是 CloneTransNo 而 dcTransNo 只是 TransNo?您的示例数据和提供的代码使用不同的名称。另外,如果您使用 scope_identity() 是否可以解决问题?我怀疑它会
  • 是的,抱歉 dcTransNoCopy 是 CloneTransNo 而 dcTransNo 只是 TransNo。
  • 您向我们展示的代码SET dcTransNoCopy = @identity WHERE dcTransNo = @identity 永远不会导致4,3。两列将始终具有相同的值。
  • 嗨,马丁,这实际上发生在我身边,几天来一直让我发疯。
  • 嗯,这不是您向我们展示的代码。这永远不能对dcTransNoCopydcTransNo 具有不同的值负责。您还没有向我们展示此内容。

标签: sql sql-server


【解决方案1】:

您需要使用 SCOPE_IDENTITY() 而不是 @@identity

更多信息here

【讨论】:

  • 嗨,bhs,我已经尝试过使用 scope_identity,这就是我切换到 @@identity 但之前没有在查询中添加 begin tran 的原因。我看看会发生什么。顺便说一句,感谢您的快速回复。
  • 没问题 - scope_identity() 正是为了这个目的,所以它应该可以工作:-)
【解决方案2】:

你为什么不使用输出表?

DECLARE @InsertedRows TABLE (ProductID INT, ProductNumber NVARCHAR(25) ) 
INSERT Product ([Name], ProductNumber, ListPrice) 
OUTPUT inserted.ProductID, inserted.ProductNumber 
INTO @InsertedRows 
SELECT [Name], ProductNumber, ListPrice 
FROM ProductsToInsert AS I 
WHERE NOT EXISTS (SELECT 1 FROM Product WHERE ProductNumber = I.ProductNumber) 

UPDATE ProductsToInsert 
SET InsertedIdentityValue = T.ProductID 
FROM ProductsToInsert I 
JOIN @InsertedRows T ON T.ProductNumber = I.ProductNumber 

SELECT RowID, ProductNumber, InsertedIdentityValue 
FROM ProductsToInsert 
WHERE InsertedIdentityValue IS NOT NULL 

这是来自http://www.sqlteam.com/article/using-the-output-clause-to-capture-identity-values-on-multi-row-inserts

【讨论】:

  • 嗨,Mathese,感谢这些,对输出一无所知。这是否取代了 scope_identity() 以有效地捕获事务中的身份?
  • 您好,是的,您不必再使用 scope_identity。微软分类查找身份的方法是这样的:@@identity 在同一个 pid 中不安全,scope_identifie 在不同的 pid 中不安全,输出最佳实践。看看它来自的文章:)
  • 我现在将查询替换为输出。将监测结果。非常感谢!
猜你喜欢
  • 1970-01-01
  • 2017-05-23
  • 1970-01-01
  • 2015-01-20
  • 2013-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-31
相关资源
最近更新 更多