在多线程环境中的 SQL Server 中插入后获取 ID?
Posted
技术标签:
【中文标题】在多线程环境中的 SQL Server 中插入后获取 ID?【英文标题】:Get Id after an INSERT in SQL Server in a multithread enviromment? 【发布时间】:2010-10-12 07:05:01 【问题描述】:如何在 SQL Server 中插入后获取 id?
对于我的插入,我使用context.ExecuteStoreCommand()
警告:我有一个多线程应用程序,它“同时”在同一个表中插入一些数据。
【问题讨论】:
【参考方案1】:SELECT SCOPE_IDENTITY()
在您的插入语句之后使用它,它将返回您在您的范围内插入的标识。您可以将其分配给变量或在输出参数中返回。
【讨论】:
是的。查看msdn.microsoft.com/en-us/library/ms190315.aspx 了解SCOPE_IDENTITY 的详细文档 SCOPE_IDENTITY() 与@@identity 有何不同,SCOPE_IDENTITY() 本身返回@@identity... 在我的回答中,我在插入后返回了@@identity...跨度> SELECT SCOPE_IDENTITY() 在我的 INSERT 之后返回 null ?! context.ExecuteStoreQuery对于这种情况,您应该使用Scope_Identity()
。这将返回当前范围的标识。 @@Identity
返回最后插入的标识。
看看Scope Identity on MSDN - 与使用Scope_Identity
相比,@@Identity
将返回错误值的示例
【讨论】:
【参考方案3】:试试这个
@@identity
下面的示例代码
strSQL = "INSERT INTO tablename (name) VALUES (@name);SELECT @@Identity"
SQLCommand.CommandText = strSQL
Id = SQLCommand.ExecuteScalar()
【讨论】:
@Numenor - 你在说什么?这是完全线程安全的,因为两个命令都在一个查询中执行。 @Patrice Pezillier,你怎么说这不是线程安全的......你检查过插入语句吗?? @Ramesh - 在 MS SQL Server 中检索身份值时,您应该始终使用Scope_Identity()
而不是 @@Identity
。 Scope_Identity 返回当前作用域的标识值,@@Identity 返回最后插入的标识。在当前范围内可能已插入也可能未插入。有关示例,请参阅msdn.microsoft.com/en-us/library/ms190315.aspx
(没有投票)- SCOPE_IDENTITY 比@@IDENTITY 更受欢迎,主要是因为触发器的问题。但是那些声称它不是线程安全的也是错误的,并且可能正在考虑 IDENT_CURRENT
@Barry,谢谢你的链接,我明白了。但在这种情况下,范围是单一的,所以不会造成任何问题......【参考方案4】:
另一种实现方法是使用 T-SQL 语言的OUTPUT 子句。
例如:
create table #tmpTable
(
ID int identity(1,1) not null primary key,
SomeValue varchar(20) not null
);
insert #tmpTable
output INSERTED.ID
values('SomeTextData')
drop table #tmpTable;
从整体解决方案设计的角度来看,我建议您将插入逻辑包装到您从应用程序源代码调用的存储过程(返回插入的记录 ID)中。
【讨论】:
【参考方案5】:我认为您可以编写一个具有输入/输出参数的存储过程,然后从参数中获取值。
【讨论】:
【参考方案6】:如果您需要标识值,我很确定您会想要使用ObjectContext.ExecuteStoreQuery 方法,而不是ObjectContext.ExecuteStoreCommand。
您需要使用SCOPE_IDENTITY()
,而不是@@IDENTITY
,因为SCOPE_IDENTITY()
返回当前执行范围的标识值,而@@IDENTITY
“是一个系统函数,它返回最后一个-插入的标识值。”
这样的事情应该可以解决问题:
using(var context = GetAContextThatsReadyToUse())
var valueForColumn1 = 5;
var result = ExecuteStoreQuery<int>("INSERT INTO table1 (Column1) VALUES (0);SELECT SCOPE_IDENTITY()", valueForColumn1);
foreach(var item in result)
// Should only return one result, which is the identity value inserted by ExecuteStoreQuery
Console.WriteLine(item);
【讨论】:
【参考方案7】:我遇到过很多情况,比如 100 个进程一次在一张表上写入。我没有使用SCOPE_IDENTITY()
,而是将整个插入/ID 提取包装到一个事务中,这种方法没有任何问题。
【讨论】:
【参考方案8】:参考SQL Server - Return value after INSERT
INSERT INTO table (name)
OUTPUT Inserted.ID
VALUES('bob');
【讨论】:
以上是关于在多线程环境中的 SQL Server 中插入后获取 ID?的主要内容,如果未能解决你的问题,请参考以下文章
scanf(), std::cin 在多线程环境中的行为如何?