当前位置:  开发笔记 > 编程语言 > 正文

获取插入行的标识的最佳方法是什么?

如何解决《获取插入行的标识的最佳方法是什么?》经验,为你挑选了10个好方法。

IDENTITY插入行的最佳方法是什么?

我知道@@IDENTITYIDENT_CURRENTSCOPE_IDENTITY,但不明白连接到每个利弊.

有人可以解释一下这些差异,以及何时应该使用它们?



1> bdukes..:

@@IDENTITY返回在所有范围内为当前会话中的任何表生成的最后一个标识值. 你需要在这里小心,因为它跨越范围.您可以从触发器获取值,而不是当前语句.

SCOPE_IDENTITY()返回为当前会话中的任何表和当前范围生成的最后一个标识值. 一般你想要使用什么.

IDENT_CURRENT('tableName')返回在任何会话和任何范围内为特定表生成的最后一个标识值.这使您可以指定您想要该值的表,以防上述两个不是您需要的(非常罕见).此外,正如@ Guy Starbuck所提到的,"如果你想获得未插入记录的表的当前IDENTITY值,你可以使用它."

OUTPUT条款的的INSERT声明将让您访问每一个经该语句插入行.由于它的范围是特定的声明,因此它比上面的其他函数更直接.但是,它更冗长(您需要插入表变量/临时表然后查询),即使在回滚语句的错误情况下,它也会给出结果.也就是说,如果您的查询使用并行执行计划,这是获取身份的唯一保证方法(不能关闭并行性).但是,它触发器之前执行,不能用于返回触发器生成的值.


为了防止其他人受到惊吓,上面提到的错误在SQL Server 2008 R2 Service Pack 1的累积更新5中得到了修复.
SCOPE_IDENTITY()的已知错误返回错误的值:http://blog.sqlauthority.com/2009/03/24/sql-server-2008-scope_identity-bug-with-multi-processor-parallel-plan-and-solution /解决方法是不在多处理器并行计划中运行INSERT或使用OUTPUT子句
几乎每次我想要'身份',我都想知道我刚刚插入的记录的密钥.如果这是您的情况,您想要使用OUTPUT子句.如果你想要别的东西,请努力阅读并理解bdukes的反应.
使用`output`,您无需创建临时表来存储和查询结果.只需省略输出子句的`into`部分,它就会将它们输出到结果集中.

2> Orry..:

我相信检索插入的id的最安全和最准确的方法是使用输出子句.

例如(摘自以下MSDN文章)

USE AdventureWorks2008R2;
GO
DECLARE @MyTableVar table( NewScrapReasonID smallint,
                           Name varchar(50),
                           ModifiedDate datetime);
INSERT Production.ScrapReason
    OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate
        INTO @MyTableVar
VALUES (N'Operator error', GETDATE());

--Display the result set of the table variable.
SELECT NewScrapReasonID, Name, ModifiedDate FROM @MyTableVar;
--Display the result set of the table.
SELECT ScrapReasonID, Name, ModifiedDate 
FROM Production.ScrapReason;
GO


有关获取插入ID的简洁示例,请查看:http://stackoverflow.com/a/10999467/2003325
哇噢!OUTPUT CLAUSE rocks :)这将简化我当前的任务.以前不知道那句话.感谢你们!
是的,这是正确的方法,如果你不在SQL Server 2008上,只使用其中一个(我们跳过了2005,所以不确定OUTPUT是否可用)

3> Orion Edward..:

我说的和其他人一样,所以每个人都是对的,我只是想让它更清楚.

@@IDENTITY返回客户端连接到数据库的最后一个东西的id.
大部分时间这种方法都可以正常工作,但有时触发器会插入一个你不知道的新行,你将从这个新行中获取ID,而不是你想要的那个

SCOPE_IDENTITY()解决了这个问题.它返回发送到数据库的SQL代码中插入的最后一个内容的id .如果触发器去创建额外的行,它们将不会导致返回错误的值.万岁

IDENT_CURRENT返回任何人插入的最后一个ID.如果某个其他应用程序恰好在不合适的时间插入另一行,您将获得该行的ID而不是您的ID.

如果您想安全地玩,请始终使用SCOPE_IDENTITY().如果您坚持使用@@IDENTITY并且有人决定稍后添加触发器,则所有代码都将中断.



4> Ian Kemp..:

获取新插入行的标识的最佳(读取:最安全)方法是使用以下output子句:

create table TableWithIdentity
           ( IdentityColumnName int identity(1, 1) not null primary key,
             ... )

-- type of this table's column must match the type of the
-- identity column of the table you'll be inserting into
declare @IdentityOutput table ( ID int )

insert TableWithIdentity
     ( ... )
output inserted.IdentityColumnName into @IdentityOutput
values
     ( ... )

select @IdentityValue = (select ID from @IdentityOutput)


SQL Server群集是一种高可用性功能,与并行性无关.单行插入(`scope_identity()`的最常见情况)无论如何都要获得并行计划是非常罕见的.这个错误在这个答案之前一年多修复了.

5> 小智..:

SELECT CAST(scope_identity() AS int);

到插入sql语句的末尾,然后

NewId = command.ExecuteScalar()

将检索它.



6> Ian Boyd..:

使用Entity Framework时,它在内部使用该OUTPUT技术返回新插入的ID值

DECLARE @generated_keys table([Id] uniqueidentifier)

INSERT INTO TurboEncabulators(StatorSlots)
OUTPUT inserted.TurboEncabulatorID INTO @generated_keys
VALUES('Malleable logarithmic casing');

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

输出结果存储在临时表变量中,连接回表,并将行值返回表中.

注意:我不知道为什么EF会将短暂的表连接回真实表(在什么情况下两者不匹配).

但这就是EF所做的.

此技术(OUTPUT)仅适用于SQL Server 2008或更高版本.


我想象它们与它们匹配以确保完整性(例如,在乐观并发模式下,当您从表变量中选择时,可能有人删除了插入程序行)。另外,也喜欢您的`TurboEncabulators` :)

7> Jakub Šturc..:

MSDN

@@ IDENTITY,SCOPE_IDENTITY和IDENT_CURRENT是类似的函数,因为它们返回插入表的IDENTITY列的最后一个值.

@@ IDENTITY和SCOPE_IDENTITY将返回当前会话中任何表中生成的最后一个标识值.但是,SCOPE_IDENTITY仅在当前范围内返回值; @@ IDENTITY不限于特定范围.

IDENT_CURRENT不受范围和会话的限制; 它仅限于指定的表格.IDENT_CURRENT返回在任何会话和任何范围内为特定表生成的标识值.有关更多信息,请参阅IDENT_CURRENT.

IDENT_CURRENT是一个以表为参数的函数.

当您在表格上有触发器时,@@ IDENTITY可能会返回令人困惑的结果

SCOPE_IDENTITY大部分时间都是你的英雄.



8> Guy Starbuck..:

@@ IDENTITY是使用当前SQL连接插入的最后一个标识.这是从插入存储过程返回的一个很好的值,您只需要为新记录插入标识,并且不关心以后是否添加了更多行.

SCOPE_IDENTITY是使用当前SQL连接插入的最后一个标识,并且在当前范围内 - 也就是说,如果在插入后基于触发器插入了第二个IDENTITY,则它不会反映在SCOPE_IDENTITY中,只会反映您执行的插入.坦率地说,我从来没有理由使用它.

无论连接或范围如何,IDENT_CURRENT(tablename)都是插入的最后一个标识.如果要获取尚未插入记录的表的当前IDENTITY值,可以使用此方法.


您不应该为此目的使用@@ identity.如果有人稍后添加了触发器,您将失去数据完整性.@@ identiy是一种极其危险的做法.

9> MarredCheese..:

我无法与其他版本的SQL Server通信,但在2012年,直接输出工作正常.您不需要打扰临时表.

INSERT INTO MyTable
OUTPUT INSERTED.ID
VALUES (...)

顺便说一下,这种技术在插入多行时也有效.

INSERT INTO MyTable
OUTPUT INSERTED.ID
VALUES
    (...),
    (...),
    (...)

产量

ID
2
3
4



10> erikkallen..:

总是使用scope_identity(),不需要任何其他东西.


不完全*从不*但是100次中的99次,你将使用Scope_Identity().
如果使用INSERT-SELECT插入多行,则需要使用OUTPUT子句捕获多个ID
查看Orry(http://stackoverflow.com/a/6073578/2440976)这个问题的答案 - 并行,并且作为一种最佳实践,你应该明智地遵循他的设置......真是太棒了!
推荐阅读
惬听风吟jyy_802
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有