2015-04-29 42 views
0

通常的做法是在INSERT后面使用@@IDENTITY变量获取表格的新创建的IDENTITY使用@@ DBTS在INSERT后检索新的rowversion是否安全?

以类似的方式使用@@DBTS的值检索UPDATE后面的最后一个rowversion值是否等于正确?

例如:

IF(OBJECT_ID('XXX') IS NOT NULL) 
    DROP TABLE XXX 
GO 
CREATE TABLE XXX 
(
    ID int IDENTITY(1,1) PRIMARY KEY, 
    Name varchar(64) NOT NULL, 
    RV rowversion 
) 
GO 
INSERT INTO XXX(Name) VALUES 
    ('Apples'),('Bananas'),('Cranberries'),('Dragon Fruit'),('Eggplant'),('Fig'),('Grape') 
GO 
SELECT * FROM XXX 
GO 
UPDATE XXX 
    SET Name = 'Chocolate' WHERE ID = 3 
PRINT @@DBTS 
GO 

现在是@@DBTS从并发更新安全吗?

如果另一个连接在UPDATEPRINT之间执行插入和更新操作,那么我们最终将得到rowversion的“其他”连接而不是我们自己更新的连接吗?

+2

使用'@ Identity'不处理并发或随后的插入在另一个范围内发生(例如在触发器中)。通常会使用[SCOPE_IDENTITY](https://msdn.microsoft.com/en-us/library/ms190315.aspx)。 – Richard

+1

对于数据库上的并发操作,“@@ DBTS”不安全。你不能保证该版本与你的'插入/更新/删除'相关。 – ughai

+0

谢谢。我对'@@ DBTS'怀疑得很多,但我没有意识到'@@ IDENTITY'也不是线程安全的。我有一些重构工作要做​​! –

回答

0

根据MSDN @@DBTS

返回当前数据库

的上次使用时间戳值。这意味着它不是线程安全的。您也不应该使用@@IDENTITY@@IDENTITYSCOPE_IDENTITY返回当前会话中任何表中生成的最后一个身份值。但是,SCOPE_IDENTITY仅在当前范围内返回该值; @@IDENTITY不限于特定的范围。 @@IDENTITY可以例如返回错误的值,如果触发器在具有标识列的表上执行。

+1

所以我唯一选择新rowversion的方法是在'UPDATED.RV'中使用'OUTPUT'子句(在我的例子中)? –

+0

是的,使用'OUTPUT'子句是最优雅的解决方案。 – Jaco