2011-10-27 74 views
192

我想在INSERT语句后返回键值。例如: 我有一个表的属性名称和ID。 id是一个生成的值。SQL Server - INSERT后的返回值

INSERT INTO table (name) VALUES('bob'); 

现在我想在相同的步骤中取回id。这是如何完成的?

我们正在使用Microsoft SQL Server 2008

+0

我发现了一个有用的答案在这里:PreparedStatement的 - 与语句返回生成的密钥] [1] [1]:http://stackoverflow.com/questions/4224228/preparedstatement- with-statement-return-generated-keys –

+1

[获取插入行标识的最佳方式?](http://stackoverflow.com/questions/42648/best-way-to-get-identity-of-inserted -row) –

回答

315

无需要单独SELECT ...

INSERT INTO table (name) 
OUTPUT Inserted.ID 
VALUES('bob'); 

这适用于非标识列(如GUID)的太

+12

你能否详细说明一下?在这个例子中输出到哪里去了? [文档](http://technet.microsoft.com/en-us/library/ms177564.aspx)仅显示表格的示例(使用output ... into)。理想情况下,我希望能够将它传递给变量 –

+2

@JonnyLeeds:您无法将其转换为变量(除非表变量)。输出到客户端或表 – gbn

+2

不幸的是,你不能依靠这个,因为向表中添加触发器会破坏你的语句!重新:http://blogs.msdn.com/b/sqlprogrammability/archive/2008/07/11/update-with-output-clause-triggers-and-sqlmoreresults.aspx – hajikelist

116

使用SCOPE_IDENTITY()以获取新的ID值

INSERT INTO table (name) VALUES('bob'); 

SELECT SCOPE_IDENTITY() 

http://msdn.microsoft.com/en-us/library/ms190315.aspx

+4

假设'id'是身份 –

+8

@ liho1eye - OP将身份列名称称为'id',所以是的。 – Curt

+1

在较大的系统上,如果许多sql同时运行会怎么样?它会将最后插入的ID返回给每个请求吗? – Shiv

25
INSERT INTO files (title) VALUES ('whatever'); 
SELECT * FROM files WHERE id = SCOPE_IDENTITY(); 

是最安全的选择,因为在带触发器的表上存在OUTPUT子句冲突的已知问题。即使您的表格当前没有触发器,也会使其变得相当不可靠 - 有人在该行中添加一个会破坏您的应用程序。时间炸弹的行为。

请参阅MSDN文章进行更深入的解释:

http://blogs.msdn.com/b/sqlprogrammability/archive/2008/07/11/update-with-output-clause-triggers-and-sqlmoreresults.aspx

+0

这是迄今为止最好的答案。 –

-2

*连接字符串中的参数顺序有时是很重要的。 *提供者参数的位置可以在添加一行后破坏记录集游标。我们看到了SQLOLEDB提供者的这种行为。

添加行后,行字段不可用,除非在连接字符串中将提供程序指定为第一个参数。当提供程序位于连接字符串中除第一个参数以外的任何位置时,新插入的行字段不可用。当我们将提供者移动到第一个参数时,奇怪地出现了行字段。

+1

您能否告诉我们该评论如何回答/与被问到的问题有关?我不觉得它值得大胆/大胆。如果你的答案被认为是有用的,用户将投票。 –

+0

很多用户可能来到此页面,因为他们没有有效的字段来标识刚添加的行。我们发现这种行为(即简单地改变连接字符串中参数的顺序,可以立即访问新添加的行)非常奇怪,我认为它应该在大写中提到,尤其是因为它很可能会修复人们希望新行ID和该行的其他字段。通过简单地将提供者作为第一个参数,问题就消失了。 –

+0

你需要编辑和改进你的答案。它目前很嘈杂,并不是一个体面的答案,甚至没有尝试 – James

0

这是我如何使用OUTPUT插入插入到SQL Server中使用ID作为标识列的表时:

'myConn is the ADO connection, RS a recordset and ID an integer 
Set RS=myConn.Execute("INSERT INTO M2_VOTELIST(PRODUCER_ID,TITLE,TIMEU) OUTPUT INSERTED.ID VALUES ('Gator','Test',GETDATE())") 
ID=RS(0) 
11

实体框架执行类似的东西,以GBN的回答是:

DECLARE @generated_keys table([Id] uniqueidentifier) 

INSERT INTO Customers(FirstName) 
OUTPUT inserted.CustomerID INTO @generated_keys 
VALUES('bob'); 

SELECT t.[CustomerID] 
FROM @generated_keys AS g 
    JOIN dbo.Customers AS t 
    ON g.Id = t.CustomerID 
WHERE @@ROWCOUNT > 0 

输出结果存储在临时表变量中,然后选择回客户端。必须知道的疑难杂症的:

刀片可以生成多个行,所以变量可以持有多单排,这样你就可以返回一个以上的ID

我没有想法为什么EF将内部加入临时表回到真正的表(在什么情况下两个不匹配)。

但这就是EF所做的。

SQL Server 2008或更高版本。如果是2005年,那么你运气不好。

8

@@ IDENTITY是返回最后插入的标识值的系统函数。

0

你可以在你的insert语句中附加一个select语句。 Integer myInt = 插入到table1(FName)值('Fred');选择Scope_Identity(); 这将在执行缩放器时返回标识的值。