我正在尝试在INSERT语句之后找回键值。示例:我有一个带有属性名称和ID的表。id是一个生成的值。
INSERT INTO table (name) VALUES('bob');
现在,我想在同一步骤中重新获得ID。怎么做?
我们正在使用Microsoft SQL Server 2008。
我正在尝试在INSERT语句之后找回键值。示例:我有一个带有属性名称和ID的表。id是一个生成的值。
INSERT INTO table (name) VALUES('bob');
现在,我想在同一步骤中重新获得ID。怎么做?
我们正在使用Microsoft SQL Server 2008。
Answers:
无需单独的SELECT ...
INSERT INTO table (name)
OUTPUT Inserted.ID
VALUES('bob');
这也适用于非IDENTITY列(例如GUID)
使用SCOPE_IDENTITY()
以获取新的ID值
INSERT INTO table (name) VALUES('bob');
SELECT SCOPE_IDENTITY()
id
是身份
id
,所以可以。
INSERT INTO files (title) VALUES ('whatever');
SELECT * FROM files WHERE id = SCOPE_IDENTITY();
这是最安全的选择,因为在带有触发器的表上存在OUTPUT子句冲突的已知问题。即使您的表当前没有任何触发器,也使此操作非常不可靠-一行添加一个触发器将破坏您的应用程序。定时炸弹是一种行为。
有关更多说明,请参见msdn文章:
实体框架执行类似于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年,那么您真不走运。
Customer
记录的所有其他更改,因为可能会有其他DB端逻辑对其产生影响,例如DEFAULT
在某些列,表上的触发器等上。EF更新了实体(对象)用于插入,因此客户端将获得具有ID的客户对象以及代表行当前状态的所有其他对象。
@@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];
out put
的bulk insert
和插入的select statement
。感谢您的建议
最好,最确定的解决方案是使用SCOPE_IDENTITY()
。
只是您必须在每次插入后获得作用域标识并将其保存在变量中,因为您可以在同一作用域中调用两个插入。
ident_current
并且@@identity
可能是他们的工作,但他们都没有安全的范围。您可能在大型应用程序中遇到问题
declare @duplicataId int
select @duplicataId = (SELECT SCOPE_IDENTITY())
更详细的信息在这里Microsoft docs
select @duplicataId = SCOPE_IDENTITY()
OUTPUT
子句是一种更好,更纯净的解决方案:)
您可以scope_identity()
用来选择刚插入变量中的行的ID,然后从该表中选择所需的任何列,其中id =您从中获得的身份scope_identity()
有关MSDN信息,请参见此处http://msdn.microsoft.com/zh-cn/library/ms190315.aspx
在插入命令之后,有多种方法来获取最后插入的ID。
@@IDENTITY
:它将返回当前会话中在Connection上生成的最后一个Identity值,而不管产生该值的Table和语句的范围如何SCOPE_IDENTITY()
:它返回由insert语句在当前连接的当前作用域中生成的最后一个标识值,而与表无关。IDENT_CURRENT(‘TABLENAME’)
:它返回在指定表上生成的最后一个标识值,而不管任何连接,会话或作用域如何。IDENT_CURRENT不受范围和会话的限制;它仅限于指定的表。现在,似乎很难决定哪一个将完全符合我的要求。
我最喜欢SCOPE_IDENTITY()。
如果在插入语句中将select SCOPE_IDENTITY()与TableName一起使用,则将按照您的期望获得确切的结果。
资料来源:CodoBee
在对带有标识列的表进行插入之后,可以引用@@ IDENTITY以获取值:http : //msdn.microsoft.com/zh-cn/library/aa933167%28v=sql.80%29.aspx
*连接字符串中的参数顺序有时很重要。*提供者参数的位置可以在添加一行后中断记录集游标。我们在SQLOLEDB提供程序中看到了这种行为。
添加行后,行字段将不可用,除非将提供程序指定为连接字符串中的第一个参数。当提供程序位于连接字符串中除第一个参数以外的任何位置时,新插入的行字段将不可用。当我们将Provider移到第一个参数时,行字段神奇地出现了。