SQL Server - INSERT 后返回值
我试图在 INSERT 语句后获取键值。 例子: 我有一个包含属性名称和 ID 的表。 id 是生成的值。
INSERT INTO table (name) VALUES('bob');
现在我想在同一步骤中取回 id。这是怎么做到的?
我们使用的是 Microsoft SQL Server 2008。
I'm trying to get a the key-value back after an INSERT-statement.
Example:
I've got a table with the attributes name and id. id is a generated value.
INSERT INTO table (name) VALUES('bob');
Now I want to get the id back in the same step. How is this done?
We're using Microsoft SQL Server 2008.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(15)
不需要单独的 SELECT...
这也适用于非 IDENTITY 列(例如 GUID)
No need for a separate SELECT...
This works for non-IDENTITY columns (such as GUIDs) too
使用
SCOPE_IDENTITY()
获取新的 ID 值http: //msdn.microsoft.com/en-us/library/ms190315.aspx
Use
SCOPE_IDENTITY()
to get the new ID valuehttp://msdn.microsoft.com/en-us/library/ms190315.aspx
这是最安全的选择,因为在带有触发器的表上存在 OUTPUT 子句冲突的已知问题。这使得这非常不可靠,因为即使您的表当前没有任何触发器 - 有人添加一个触发器也会破坏您的应用程序。定时炸弹之类的行为。
请参阅 msdn 文章以获取更深入的解释:
http://blogs.msdn.com/b/sqlprogrammability/archive/2008/07/11/update-with-output-clause-triggers-and-sqlmoreresults.aspx
Is the safest bet since there is a known issue with OUTPUT Clause conflict on tables with triggers. Makes this quite unreliable as even if your table doesn't currently have any triggers - someone adding one down the line will break your application. Time Bomb sort of behaviour.
See msdn article for deeper explanation:
http://blogs.msdn.com/b/sqlprogrammability/archive/2008/07/11/update-with-output-clause-triggers-and-sqlmoreresults.aspx
实体框架执行类似于 gbn 的答案的操作:
输出结果存储在临时表变量中,然后选择返回给客户端。必须注意以下问题:
我不知道为什么 EF 会将临时表内部连接回真实表表(什么情况下两者不匹配)。
但这就是 EF 所做的。
仅限 SQL Server 2008 或更高版本。如果是 2005 年,那你就不走运了。
Entity Framework performs something similar to gbn's answer:
The output results are stored in a temporary table variable, and then selected back to the client. Have to be aware of the gotcha:
I have no idea why EF would inner join the ephemeral table back to the real table (under what circumstances would the two not match).
But that's what EF does.
SQL Server 2008 or newer only. If it's 2005 then you're out of luck.
插入后退出的方式有很多种
IDENT_CURRENT:它返回在任何会话中为特定表或视图创建的最后一个标识。
SCOPE_IDENTITY:它返回同一会话和同一范围的最后一个身份。范围是存储过程/触发器等。
@@IDENTITY:它返回同一会话中的最后一个身份。
There are many ways to exit after insert
IDENT_CURRENT: It returns the last identity created for a particular table or view in any session.
SCOPE_IDENTITY: It returns the last identity from a same session and the same scope. A scope is a stored procedure/trigger etc.
@@IDENTITY: It returns the last identity from the same session.
@@IDENTITY
是一个系统函数,返回最后插入的标识值。@@IDENTITY
Is a system function that returns the last-inserted identity value.有多种方法可以获取插入命令后最后插入的 ID。
@@IDENTITY
:它返回当前会话中连接上生成的最后一个 Identity 值,无论生成该值的表和语句范围如何SCOPE_IDENTITY()
:它返回无论表如何,当前连接的当前作用域中的 insert 语句生成的最后一个标识值。IDENT_CURRENT('TABLENAME')
:它返回指定表上生成的最后一个标识值,无论任何连接、会话或范围如何。 IDENT_CURRENT不受范围和会话的限制;它仅限于指定的表。现在似乎更难决定哪一个将完全符合我的要求。
我最喜欢 SCOPE_IDENTITY()。
如果您在 insert 语句中使用 select SCOPE_IDENTITY() 和 TableName,您将得到符合您期望的准确结果。
来源: CodoBee< /a>
There are multiple ways to get the last inserted ID after insert command.
@@IDENTITY
: It returns the last Identity value generated on a Connection in current session, regardless of Table and the scope of statement that produced the valueSCOPE_IDENTITY()
: It returns the last identity value generated by the insert statement in the current scope in the current connection regardless of the table.IDENT_CURRENT(‘TABLENAME’)
: It returns the last identity value generated on the specified table regardless of Any connection, session or scope. IDENT_CURRENT is not limited by scope and session; it is limited to a specified table.Now it seems more difficult to decide which one will be exact match for my requirement.
I mostly prefer SCOPE_IDENTITY().
If you use select SCOPE_IDENTITY() along with TableName in insert statement, you will get the exact result as per your expectation.
Source : CodoBee
最好、最可靠的解决方案是使用 SCOPE_IDENTITY()。
只是您必须在每次插入后获取范围标识并将其保存在变量中,因为您可以在同一范围内调用两个插入。
ident_current
和@@identity
可能有效,但它们不是安全范围。您可能会在大型应用程序中遇到问题更多详细信息请参见微软文档
The best and most sure solution is using
SCOPE_IDENTITY()
.Just you have to get the scope identity after every insert and save it in a variable because you can call two insert in the same scope.
ident_current
and@@identity
may be they work but they are not safe scope. You can have issues in a big applicationMore detail is here Microsoft docs
您可以使用
scope_identity()
选择刚刚插入变量的行的 ID,然后只需从该表中选择您想要的任何列,其中 id = 您从scope_identity( 获得的标识) )
请参阅此处获取 MSDN 信息 http://msdn.microsoft.com/en-us/library/ms190315.aspx
You can use
scope_identity()
to select the ID of the row you just inserted into a variable then just select whatever columns you want from that table where the id = the identity you got fromscope_identity()
See here for the MSDN info http://msdn.microsoft.com/en-us/library/ms190315.aspx
推荐使用 SCOPE_IDENTITY() 来获取新的 ID 值,但不使用“OUTPUT Inserted.ID”
如果插入语句抛出异常,我除外它直接抛出它。但“OUTPUT Inserted.ID”将返回 0,这可能与预期不符。
Recommend to use SCOPE_IDENTITY() to get the new ID value, But NOT use "OUTPUT Inserted.ID"
If the insert statement throw exception, I except it throw it directly. But "OUTPUT Inserted.ID" will return 0, which maybe not as expected.
已确认的答案对于 MS SQL Servers Transact-SQL 是正确的,但如果您想对 PostgreSQL 执行此操作,则需要使用
RETURNING
子句:The confirmed answer is correct for MS SQL Servers Transact-SQL, but if you'd want to do it for PostgreSQL, you would need to use the
RETURNING
clause:您可以将 select 语句附加到 insert 语句中。
当执行标量时,这将返回一个身份值。
You can append a select statement to your insert statement.
This will return a value of the identity when executed scalar.
这就是我在 SQL Server 中插入到使用 ID 作为标识列的表时使用 OUTPUT INSERTED 的方式:
This is how I use OUTPUT INSERTED, when inserting to a table that uses ID as identity column in SQL Server:
在对带有标识列的表进行插入操作后,您可以引用 @@IDENTITY 来获取值:
http://msdn.microsoft.com/en -us/library/aa933167%28v=sql.80%29.aspx
After doing an insert into a table with an identity column, you can reference @@IDENTITY to get the value:
http://msdn.microsoft.com/en-us/library/aa933167%28v=sql.80%29.aspx
* 连接字符串中的参数顺序有时很重要。 * Provider 参数的位置可能会在添加行后破坏记录集游标。我们在 SQLOLEDB 提供程序中看到了这种行为。
添加行后,行字段不可用,除非将提供程序指定为连接字符串中的第一个参数。当提供程序位于连接字符串中除第一个参数之外的任何位置时,新插入的行字段不可用。当我们将 Provider 移至第一个参数时,行字段神奇地出现了。
* Parameter order in the connection string is sometimes important. * The Provider parameter's location can break the recordset cursor after adding a row. We saw this behavior with the SQLOLEDB provider.
After a row is added, the row fields are not available, UNLESS the Provider is specified as the first parameter in the connection string. When the provider is anywhere in the connection string except as the first parameter, the newly inserted row fields are not available. When we moved the the Provider to the first parameter, the row fields magically appeared.