Difference between SCOPE_IDENTITY(), @@IDENTITY, and IDENT_CURRENT

本文详细解释了SQL中IDENTITY, SCOPE_IDENTITY(),和IDENT_CURRENT()函数的区别,重点讨论了它们如何在不同场景下表现不同行为,以及在触发器作用下IDENTITY与SCOPE_IDENTITY之间的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

原文:

http://www.go4coding.com/post/2011/06/16/Difference-between-Scope_Identity()Identity-and-Ident_Current.aspx

 

 

In this post, we will discuss on the difference among @@IDENTITY, SCOPE_IDENTITY(), and IDENT_CURRENT().

@@IDENTITY, SCOPE_IDENTITY(), and IDENT_CURRENT() are used to fetch the last inserted identity value. Most of the cases, we find that these functions return the same value indicating to an identity column. But these function are not really same, they show different behavior at different scenario.

Let's discuss now-
@@IDENTITY: It is a global variable that returns the last identity value inserted into any table in the current session, across any scopes.As @@IDENTITY is free of scope,so if an insert statement becomes the cause of insertion in some other table (In case of trigger),then @@IDENTITY will fetch the last inserted value in identity column of the table on which data was inserted in last.


SCOPE_IDENTITY: This function returns the last identity value inserted into any table in the current session and the current scope. So you will always get the value that was inserted in last by your insert statement in the identity column, regardless whether insertion happens with your insert statements in any table or you execute any procedure that is doing any insertion operation in any table.


IDENT_CURRENT: This function returns the last identity value generated (no matter it was inserted or not) for a specific table in any session and any scope. In simple words, IDENT_CURRENT() function gives the value that was at least generated as an identity for a specific table. I want to focus on the word “generated” instead of “inserted” because it is possible that the identity is generated by insert statement but could not be inserted due to run time error.


To show the difference among these function, we will create two tables with name Demo_A and Demo_B and then create an after-trigger on table Demo_A with name InsertionInDemoB.

CREATE TABLE Demo_A
(
id INT IDENTITY,
A_data VARCHAR(10)
)
go
CREATE TABLE Demo_B
(
id INT IDENTITY(2,2),
B_data VARCHAR(10)
)
go 
CREATE TRIGGER InsertionInDemoB ON Demo_A
FOR INSERT
AS
BEGIN
INSERT INTO Demo_B VALUES((SELECT A_data FROM inserted))
END

Run the following command and observe the result....

insert into Demo_A values('ABC')
select @@IDENTITY as [@@IDENTITY],SCOPE_IDENTITY() 
as [SCOPE_IDENTITY],IDENT_CURRENT('Demo_A') as [IDENT_CURRENT]

Why the @@IDENTITY and SCOPE_IDENTITY differ in result? The reason is that @@IDENTITY can not be limited with current scope.. so it is indicating the  Demo_B table because a insert command is also running on Demo_B after the execution of insert command on  Demo_A-table (because of trigger InsertionInDemoB). Now what is the Difference  between IDENT_CURRENT() and SCOPE_IDENTITY() functions, As we have already discuss that IDENT_CURRENT() is also free from the current scope limitation so by changing name of table in its argument, you can see the last generated identity value for the specify table. Here again I want to draw focus that IDENT_CURRENT() works on the identity value that is last generated for a table while @@IDENTITY and SCOPE_IDENTITY works on the identity value that are inserted in a table.Run the following command and observe the result....

BEGIN TRY
insert into Demo_B values('The statement will be terminated.')
END TRY
BEGIN CATCH
select @@IDENTITY as [@@IDENTITY],SCOPE_IDENTITY() as [SCOPE_IDENTITY],
IDENT_CURRENT('Demo_B') as [IDENT_CURRENT]
END CATCH

In the above example, Insert statement will cause an Exception, and so no value will be inserted in table Demo_B ,yet the identity will be generated,  and this identity value can be fetched by IDENT_CURRENT while @@IDENTITY and SCOPE_IDENTITY does not change their value in such a case.

You should always remember that SCOPE_IDENTITY or IDENTITY may produce inconsistent results in case of  parallel plan execution. For more detail, check the below link--

http://support.microsoft.com/kb/2019779

Thank you for reading.

基于Spring Boot搭建的一个多功能在线学习系统的实现细节。系统分为管理员和用户两个主要模块。管理员负责视频、文件和文章资料的管理以及系统运营维护;用户则可以进行视频播放、资料下载、参与学习论坛并享受个性化学习服务。文中重点探讨了文件下载的安全性和性能优化(如使用Resource对象避免内存溢出),积分排行榜的高效实现(采用Redis Sorted Set结构),敏感词过滤机制(利用DFA算法构建内存过滤树)以及视频播放的浏览器兼容性解决方案(通过FFmpeg调整MOOV原子位置)。此外,还提到了权限管理方面自定义动态加载器的应用,提高了系统的灵活性和易用性。 适合人群:对Spring Boot有一定了解,希望深入理解其实际应用的技术人员,尤其是从事在线教育平台开发的相关从业者。 使用场景及目标:适用于需要快速搭建稳定高效的在线学习平台的企业或团队。目标在于提供一套完整的解决方案,涵盖从资源管理到用户体验优化等多个方面,帮助开发者更好地理解和掌握Spring Boot框架的实际运用技巧。 其他说明:文中不仅提供了具体的代码示例和技术思路,还分享了许多实践经验教训,对于提高项目质量有着重要的指导意义。同时强调了安全性、性能优化等方面的重要性,确保系统能够应对大规模用户的并发访问需求。
<think>好的,我现在需要回答用户关于SQL Server中@@IDENTITY的使用示例的问题。用户可能想了解如何在插入数据后获取自动生成的标识值,比如自增ID。首先,我需要回忆@@IDENTITY的作用,它返回当前会话中最后生成的标识值,但需要注意触发器的潜在影响。 根据引用[3],@@IDENTITY会在INSERT等语句完成后返回最后的标识值,但如果触发器中有插入操作,它可能返回触发器产生的值,这可能导致意外结果。用户可能需要一个具体的示例来说明这一点。 我应该先提供一个基本的示例,展示插入数据后使用@@IDENTITY获取ID。然后,可以对比SCOPE_IDENTITY()和@@IDENTITY的区别,说明为何有时推荐使用SCOPE_IDENTITY()。引用[1]提到慎用@@IDENTITY,建议用SCOPE_IDENTITY(),因为后者只返回当前作用域的值,不受触发器影响。 接下来,可能需要构造一个包含触发器的例子,显示@@IDENTITYSCOPE_IDENTITY()的不同结果。例如,主表插入后触发向另一个有标识列的表插入数据,此时@@IDENTITY会返回触发器中的ID,而SCOPE_IDENTITY()返回主表的ID。这样可以直观展示差异。 另外,用户可能想知道如何安全地获取自增ID,需要强调使用场景和潜在问题。引用[4]提到在插入时可能需要开启IDENTITY_INSERT,但示例中可能不需要,除非是显式插入标识列。 最后,总结不同函数的适用情况,并生成相关问题,帮助用户进一步学习。需要确保示例代码正确,比如正确的INSERT语句和获取变量的方法,可能使用PRINT或SELECT来显示结果。同时,注意使用中文解释,保持结构清晰。</think>以下是关于SQL Server中`@@IDENTITY`的使用示例及详细说明: --- ### 1. 基本使用示例 当向**带有自增列(Identity列)的表**插入数据后,可通过`@@IDENTITY`获取最新生成的标识值: ```sql -- 创建测试表 CREATE TABLE Employees ( ID INT IDENTITY(1,1) PRIMARY KEY, Name NVARCHAR(50) ); -- 插入数据并获取自增ID INSERT INTO Employees (Name) VALUES ('张三'); SELECT @@IDENTITY AS LastInsertedID; -- 返回1 INSERT INTO Employees (Name) VALUES ('李四'); SELECT @@IDENTITY AS LastInsertedID; -- 返回2 ``` --- ### 2. 含触发器的复杂示例 当插入操作**触发其他表的插入**时,`@@IDENTITY`可能返回**触发器中的最后标识值**,而非原始表的标识值[^3]: ```sql -- 创建日志表 CREATE TABLE LogTable ( LogID INT IDENTITY(100,1) PRIMARY KEY, Action NVARCHAR(100) ); -- 创建触发器 CREATE TRIGGER trg_Employees_Insert ON Employees AFTER INSERT AS BEGIN INSERT INTO LogTable (Action) VALUES ('New employee added'); END; -- 插入数据并检查结果 INSERT INTO Employees (Name) VALUES ('王五'); SELECT @@IDENTITY AS LastInsertedID; -- 返回100(来自LogTable的LogID) SELECT SCOPE_IDENTITY() AS ScopeIdentity; -- 返回3(来自Employees的ID) ``` - **关键区别**:`@@IDENTITY`返回触发器生成的ID(100),而`SCOPE_IDENTITY()`返回当前作用域的ID(3)[^1]。 --- ### 3. 安全获取自增ID的建议 为避免触发器干扰,优先使用`SCOPE_IDENTITY()`或`OUTPUT`子句: ```sql -- 方法1:使用SCOPE_IDENTITY() INSERT INTO Employees (Name) VALUES ('赵六'); SELECT SCOPE_IDENTITY() AS SafeInsertedID; -- 返回4 -- 方法2:使用OUTPUT子句 INSERT INTO Employees (Name) OUTPUT INSERTED.ID VALUES ('孙七'); -- 直接返回5 ``` --- ### 关键函数对比 | 函数 | 作用域 | 是否受触发器影响 | 适用场景 | |--------------------|----------------------|------------------|----------------------------| | `@@IDENTITY` | 当前会话所有操作 | 是 | 需要全局最后标识值时 | | `SCOPE_IDENTITY()` | 当前作用域(如存储过程)| 否 | 安全获取当前操作标识值 | | `IDENT_CURRENT()` | 指定表的所有会话 | 否 | 跨会话查询某表的当前标识值 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值