SQL Server -在INSERT之后返回值

我试图在插入语句后得到一个键值。 例子: 我有一个表的属性名称和id。

. Id是生成的值
    INSERT INTO table (name) VALUES('bob');

现在我想在同一步骤中取回id。这是怎么做到的?

我们使用的是Microsoft SQL Server 2008。

731701 次浏览

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

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


SELECT SCOPE_IDENTITY()

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

在插入一个带有identity列的表之后,你可以引用@@IDENTITY来获取值: http://msdn.microsoft.com/en-us/library/aa933167%28v=sql.80%29.aspx < / p >

你可以使用scope_identity()来选择你刚刚插入到变量中的行ID,然后从那个表中选择你想要的任何列,其中ID =你从scope_identity()中得到的标识

MSDN信息http://msdn.microsoft.com/en-us/library/ms190315.aspx请看这里

不需要单独的SELECT…

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

这也适用于非identity列(比如guid)

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

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

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

这是我如何使用输出插入,当插入到一个表,使用ID作为标识列在SQL Server:

'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)

实体框架执行类似于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

输出结果存储在临时表变量中,然后选择返回给客户端。你必须意识到这一点:

insert可以生成多行,因此变量可以保存多行,因此可以返回多个ID

我不知道为什么EF会将临时表内部连接回实际表(在什么情况下两者会不匹配)。

但英孚就是这么做的。

仅支持SQL Server 2008或更新版本。如果是2005年,那你就不走运了。

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

你可以将一个选择语句附加到你的插入语句中。 整数myInt = 插入到表1 (FName)值('Fred');选择Scope_Identity (); 这将在执行标量时返回一个标识的值

最好和最确定的解决方案是使用SCOPE_IDENTITY()

你只需要在每次插入后获取作用域标识并将其保存在一个变量中,因为你可以在同一个作用域中调用两个插入。

ident_current@@identity可能是他们工作,但他们不是安全范围。在大型应用程序中可能会出现问题

  declare @duplicataId int
select @duplicataId =   (SELECT SCOPE_IDENTITY())

更多细节在这里微软文档

有很多方法可以在插入后退出

当您向表中插入数据时,可以使用OUTPUT子句 返回已插入到表中的数据的副本。的 OUTPUT子句有两种基本形式:OUTPUT和OUTPUT INTO。使用 如果希望将数据返回给调用应用程序,则使用OUTPUT表单。 如果希望将数据返回到表或表中,则使用OUTPUT INTO表单 一个表变量。

DECLARE @MyTableVar TABLE (id INT,NAME NVARCHAR(50));


INSERT INTO tableName
(
NAME,....
)OUTPUT INSERTED.id,INSERTED.Name INTO @MyTableVar
VALUES
(
'test',...
)

IDENT_CURRENT:它返回在任何会话中为特定表或视图创建的最后一个标识。

SELECT IDENT_CURRENT('tableName') AS [IDENT_CURRENT]

SCOPE_IDENTITY:返回同一个会话和同一个作用域的最后一个标识。作用域是存储过程/触发器等。

SELECT SCOPE_IDENTITY() AS [SCOPE_IDENTITY];

@@IDENTITY:返回同一会话的最后一个标识。

SELECT @@IDENTITY AS [@@IDENTITY];

有多种方法可以获取插入命令后最后插入的ID。

  1. @@IDENTITY:它返回当前会话中在Connection上生成的最后一个Identity值,不管产生该值的Table和语句的作用域如何
  2. SCOPE_IDENTITY():它返回当前连接中插入语句在当前作用域中生成的最后一个标识值,而不管表是什么。
  3. IDENT_CURRENT(‘TABLENAME’):它返回在指定表上生成的最后一个标识值,而不管任何连接、会话或范围。IDENT_CURRENT不受作用域和会话的限制;它仅限于指定的表。

现在似乎更难决定哪一个能完全符合我的要求。

我更喜欢SCOPE_IDENTITY()。

如果在insert语句中使用select SCOPE_IDENTITY()和TableName,您将得到您所期望的确切结果。

来源:CodoBee

建议使用SCOPE_IDENTITY()获取新的ID值,但使用"OUTPUT Inserted.ID"

如果插入语句抛出异常,我将直接抛出它。但是“OUTPUT inserted . id”;将返回0,这可能不是预期的。