被 SCOPE_IDENTITY() 和 GO 弄糊涂了
Posted
技术标签:
【中文标题】被 SCOPE_IDENTITY() 和 GO 弄糊涂了【英文标题】:Confused by SCOPE_IDENTITY() and GO 【发布时间】:2018-05-10 07:46:04 【问题描述】:我对 SQL Server 中 SCOPE_IDENTITY() 的文档和行为感到有些困惑。
这个页面https://docs.microsoft.com/en-us/sql/t-sql/functions/scope-identity-transact-sql?view=sql-server-2017 说这个关于SCOPE_IDENTITY():
返回插入到标识列中的最后一个标识值 相同的范围。作用域是一个模块:一个存储过程、触发器、 函数或批处理。因此,如果两个语句在同一个 存储过程、函数或批处理,它们在同一范围内。
它包含这个例子
USE AdventureWorks2012;
GO
INSERT INTO Person.ContactType ([Name]) VALUES ('Assistant to the Manager');
GO
SELECT SCOPE_IDENTITY() AS [SCOPE_IDENTITY];
GO
SELECT @@IDENTITY AS [@@IDENTITY];
GO
返回
SCOPE_IDENTITY
21
@@IDENTITY
21
从文档中,我认为 SCOPE_IDENTITY() 的结果将为 NULL,因为 SELECT SCOPE_IDENTITY() AS [SCOPE_IDENTITY];与 INSERT 命令在不同的 batch 中执行(因为它在 GO 之后)...我在这里缺少什么?
【问题讨论】:
您使用什么程序将这些命令发送到数据库服务器? 该示例来自文档,但我们在 SQL Server Management Studio 中看到了相同的行为(针对不同的表)。 【参考方案1】:我同意,我认为文档有点误导。 SCOPE_IDENTITY
确实在同一连接上直接执行的多个批处理中保留其值。
但请注意,如果您通过使用字符串执行 EXEC
创建 inner 批处理,则该内部批处理的 SCOPE_IDENTITY
独立于 您的 外部批处理的 @987654324 @
此脚本生成值2
,而不是5
:
create table T1 (ID int IDENTITY(2,1000) not null,Val char(1))
create table T2 (ID int IDENTITY(5,1000) not null, Val char(1))
go
insert into T1(Val) values ('a')
exec('insert into T2(Val) values (''b'')')
select SCOPE_IDENTITY()
【讨论】:
【参考方案2】:不要使用scope_indentity
。 SQL Server 有一种更好的从插入返回值的方法,即OUTPUT
子句。
DECLARE @ids TABLE (id INT);
INSERT INTO Person.ContactType ([Name])
OUTPUT inserted.ID INTO @ids -- I'm not sure what the identity is named
VALUES ('Assistant to the Manager');
这有很多好处:
除了id
之外,您还可以返回更多列。
您可以从多于一行的插入中返回 ID。
您完全不必担心范围界定。
【讨论】:
以上是关于被 SCOPE_IDENTITY() 和 GO 弄糊涂了的主要内容,如果未能解决你的问题,请参考以下文章
newsequentialid、scope_identity 和@@identity 有啥区别? [复制]
SCOPE_IDENTITY()和 SELECT @@IDENTITY 的用法
Scope_Identity()、Identity()、@@Identity 和 Ident_Current() 有啥区别?