首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL Server 取得插入後自增 ID 完整指南:@@IDENTITY、SCOPE_IDENTITY、IDENT_CURRENT 差異與最佳實務

     編輯:關於SqlServer

快速範例

CREATE DATABASE dbdemo;
GO
USE dbdemo;
GO
CREATE TABLE tbldemo (id INT PRIMARY KEY IDENTITY(1,1), name VARCHAR(20));
GO

INSERT INTO tbldemo VALUES ('測試');
SELECT @@IDENTITY;          -- 1
SELECT SCOPE_IDENTITY();    -- 1
SELECT IDENT_CURRENT('tbldemo'); -- 1

三函數核心差異

函數作用域觸發器影響適用場景
@@IDENTITY目前 Session、所有 Scope、所有 Table受影響(回傳觸發器最後 INSERT 的 ID)無觸發器的簡單環境
SCOPE_IDENTITY()目前 Session、目前 Scope、所有 Table不受影響(只看目前 Scope)最推薦、生產環境首選
IDENT_CURRENT('tbl')指定 Table、所有 Session、所有 Scope不受 Scope 限制跨 Session 監控、複寫稽核

觸發器實測

CREATE TABLE T1 (id INT IDENTITY, c1 INT);
CREATE TABLE T2 (id INT IDENTITY, c1 INT);
GO
CREATE TRIGGER tr_T1 ON T1 AFTER INSERT AS
    INSERT INTO T2 (c1) SELECT 999;
GO

INSERT INTO T1 (c1) VALUES (1);
SELECT @@IDENTITY;       -- T2 的 ID
SELECT SCOPE_IDENTITY(); -- T1 的 ID

並發測試心得(社群實測)

  • @@IDENTITY:40 執行緒並發,< 1 萬筆即發生衝突。
  • SCOPE_IDENTITY():同條件測試 零衝突,極度可靠。
  • 建議直接在預存程序中使用 SCOPE_IDENTITY(),無需額外觸發器。

實用查詢

-- 取得指定表下一個自增值
SELECT IDENT_CURRENT('TableName') + IDENT_INCR('TableName');

-- 取得種子與增量
SELECT IDENT_SEED('TableName'), IDENT_INCR('TableName');

其他資料庫對應

  • MySQL:LAST_INSERT_ID()
  • Oracle:RETURNING id INTO :v_id 或 Sequence currval
  • PostgreSQL:INSERT ... RETURNING id
  • SQLite:last_insert_rowid()

結論

生產環境一律使用 SCOPE_IDENTITY(),除非明確需要觸發器產生的 ID。避免使用 @@IDENTITY 造成難以重現的並發 Bug。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved