Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql @@标识、SCOPE_IDENTITY()、输出和其他检索上一个标识的方法_Sql_Sql Server_Tsql_Identity_Output Clause - Fatal编程技术网

Sql @@标识、SCOPE_IDENTITY()、输出和其他检索上一个标识的方法

Sql @@标识、SCOPE_IDENTITY()、输出和其他检索上一个标识的方法,sql,sql-server,tsql,identity,output-clause,Sql,Sql Server,Tsql,Identity,Output Clause,我见过在插入后检索主键标识字段的值时使用的各种方法 declare @t table ( id int identity primary key, somecol datetime default getdate() ) insert into @t default values select SCOPE_IDENTITY() --returns 1 select @@IDENTITY --returns 1 在插入后返回标识表: Create Table #Testing

我见过在插入后检索主键标识字段的值时使用的各种方法

declare @t table (
    id int identity primary key,
    somecol datetime default getdate()
)
insert into @t
default values

select SCOPE_IDENTITY() --returns 1
select @@IDENTITY --returns 1
在插入后返回标识表:

Create Table #Testing (  
    id int identity,  
    somedate datetime default getdate()  
)  
insert into #Testing  
output inserted.*  
default values   
什么方法合适或更好?输出方法的作用域安全吗


第二个代码段是从

中借用的,SQL Server 2005中还提供了另一种方法

这将允许您在插入后检索多个标识。以下是博文中的代码:

Create Table #Testing (  
    id int identity,  
    somedate datetime default getdate()  
)  
insert into #Testing  
output inserted.*  
default values

@@身份是老派的方式。在以后的所有实例中使用SCOPE_IDENTITY()。有关使用@@IDENTITY的影响,请参见(它们很糟糕!)

这取决于你想做什么

@@身份

返回在连接上生成的最后一个标识值,而不管生成该值的表是什么,也不管生成该值的语句的范围是什么。 @@IDENTITY将返回在当前会话中输入到表中的最后一个IDENTITY值@@标识仅限于当前会话,而不限于当前范围。例如,如果在一个表上有一个触发器导致在另一个表中创建标识,则您将获得最后创建的标识,即使该标识是由触发器创建的

范围_标识()

返回在连接上以及由同一范围内的语句生成的最后一个标识值,而不考虑生成该值的表。 SCOPE_IDENTITY()类似于@@IDENTITY,但它也会将值限制在当前范围内。换句话说,它将返回您显式创建的最后一个标识值,而不是由触发器或用户定义函数创建的任何标识

当前识别码()


返回表中生成的最后一个标识值,而不考虑生成该值的语句的连接和范围。IDENT_CURRENT仅限于指定的表,但不受连接或范围的限制

对Godeke的回答做了一个小小的修正:

你需要担心的不仅仅是触发因素。任何导致创建标识符的嵌套操作(如存储过程)都可能更改@@IDENTITY的值


另一次对scope_identity的投票…

scope_identity对于单行就足够了,建议您在出于某种原因(为什么?)需要查看中间触发器结果的情况下进行投票


对于多行,OUTPUT/OUTPUT INTO是您新的最佳朋友,它可以替代重新查找行并插入到另一个表中。

请注意,
scope\u identity()
@@identity
-请参阅MS Connect:

引用(来自微软):

我强烈建议在所有情况下使用
OUTPUT
而不是
@@IDENTITY
。 这是读取标识和时间戳的最好方法

编辑以添加:现在可能已修复。Connect给了我一个错误,但请参见:


在使用@@IDENTITY时要小心


在尝试获取刚刚插入的行的标识时,几乎没有理由使用除
输出
子句之外的任何内容。OUTPUT子句是范围和表安全的

下面是一个简单的示例,在插入一行后获取id

DECLARE @Inserted AS TABLE (MyTableId INT);

INSERT [MyTable] (MyTableColOne, MyTableColTwo)
OUTPUT Inserted.MyTableId INTO @Inserted
VALUES ('Val1','Val2')

SELECT MyTableId FROM @Inserted
输出条款的详细文档:



我以前见过这种情况,但我认为它不安全。意味着我可能会看到其他人的插页。我不知道那是不是真的,我不确定。我将把这个添加到问题中。输出是范围安全的。从现在起,它是首选方法。即使是SCOPE_IDENTITY()也会遇到触发器自身插入的问题。(为您提供触发器插入的最后一个表的标识)该链接中的示例代码似乎与您的声明相矛盾。很确定触发器发生在不同的范围内。@Dems,这完全不是trueWow,这是对两年前一条评论的回应。。。是的,在我添加那条评论的那天,我要么喝醉了,要么就是非常愚蠢。我只是想提到,当使用并行时,上面的错误就会出现。但这不会影响执行单个插入的情况。这是微软的一句话。“每当生成并行查询计划时@@IDENTITY和SCOPE\u IDENTITY()没有被一致更新,因此无法依赖。”SCOPE\u IDENTITY()呢?对于更多的用例,@@IDENTITY似乎总是有问题。您没有描述在SQL Server的新版本中使用输出这一首选方法。它不仅是作用域安全的,而且如果您需要进行进一步处理,它还可以返回多个标识甚至其他字段。@HLGEM,输出很好,但当您只需要一个标识值时使用起来有点笨拙。@Constantin,这是真的,这是微软获得价值的首选方式,从我读到的内容来看,他们不打算用将来的“@标识”和“SeopeIX标识”来解决任何问题,因为他们认为输出是替代品。@ HLGEM在哪里说“@身份将被输出代替?”Domcha:是的,当您尝试在具有insert-trigger的情况下运行输出时,它会告诉您这一点。注意:在游标中使用此类内容时,请确保在每次迭代中删除表变量中的所有内容,因为DECLARE不会重新初始化。
-- table structure for example:     
CREATE TABLE MyTable (
    MyTableId int NOT NULL IDENTITY (1, 1),
    MyTableColOne varchar(50) NOT NULL,
    MyTableColTwo varchar(50) NOT NULL
)