@@IDENTITY與SCOPE_IDENTITY()
在一條 INSERT、SELECT INTO 或大容量複製語句完成後,@@IDENTITY 中包含語句生成的最後一個標識值。如果語句未影響任何包含標識列的表,則 @@IDENTITY 返回 NULL。如果插入了多個行,生成了多個標識值,則 @@IDENTITY 將返回最後生成的標識值。如果語句觸發了一個或多個觸發器,該觸發器又執行了生成標識值的插入操作,那麼,在語句執行後立即呼叫 @@IDENTITY 將返回觸發器生成的最後一個標識值。如果對包含標識列的表執行插入操作後觸發了觸發器,並且觸發器對另一個沒有標識列的表執行了插入操作,則 @@IDENTITY 將返回第一次插入的標識值。出現 INSERT 或 SELECT INTO 語句失敗或大容量複製失敗,或者事務被回滾的情況時,@@IDENTITY 值不會恢復為以前的設定。
如果語句和事務失敗,它們會更改表的當前標識,從而使標識列中的值出現不連貫現象。即使未提交試圖向表中插入值的事務,也永遠無法回滾標識值。例如,如果因 IGNORE_DUP_KEY 衝突而導致 INSERT 語句失敗,表的當前標識值仍然會增加。
@@IDENTITY、SCOPE_IDENTITY 和 IDENT_CURRENT 是相似的函式,因為他們都返回插入到表的 IDENTITY 列的最後一個值。
@@IDENTITY 和 SCOPE_IDENTITY 可以返回當前會話中的所有表中生成的最後一個標識值。但是,SCOPE_IDENTITY 只在當前作用域內返回值,而 @@IDENTITY 不限於特定的作用域。
IDENT_CURRENT 不受作用域和會話的限制,而受限於指定的表。IDENT_CURRENT 可以返回任何會話和任何作用域中為特定表生成的標識值。
@@IDENTITY 函式的作用域是執行該函式的本地伺服器上的當前會話。此函式不能應用於遠端或連結伺服器。若要獲得其他伺服器上的標識值,請在遠端伺服器或連結伺服器上執行儲存過程,並使(在遠端或連結伺服器的環境中執行的)該儲存過程收集標識值,並將其返回本地伺服器上的發出呼叫的連線。
以下示例向包含標識列 (LocationID
) 的表中插入一行,並使用 @@IDENTITY
顯示新行中使用的標識值:
USE AdventureWorks; GO --Display the value of LocationID in the last row in the table. SELECT MAX(LocationID) FROM Production.Location; GO INSERT INTO Production.Location (Name, CostRate, Availability, ModifiedDate) VALUES ('Damaged Goods', 5, 2.5, GETDATE()); GO SELECT @@IDENTITY AS 'Identity'; GO --Display the value of LocationID of the newly inserted row. SELECT MAX(LocationID) FROM Production.Location; GO
補充:
我們要慎用@@IDENTITY,原因是 @@IDENTITY 它總是獲取最後一條變更資料的自增欄位的值,而忽略了進行變更操作所在的範圍約束。比如,我有表 A 和表 B 兩個表,現在我在表 A 上定義了一個Insert觸發器,當在表 A 中插入一條資料時,自動在表 B 也插入一條資料。此時,大家注意,有兩個原子操作:在A中插入一條資料, 接著在B中隨後插入一條資料。
現在我們想下,假設上面表 A 和表 B 都有IDENTITY自增域,那麼我們在表 A 插入一條資料後,使用了 SELECT @@IDENTITY 輸出時,輸出的到底是 A 還是 B 的自增域的值呢? 答案很明顯,是誰最後插入就輸出誰,那麼就是 B 了。於是,我本意是想得到 A 的自增域值,結果得到了 B 的自增域值,一隻 BUG 隨之誕生,搞不好還會影響到整個系統資料的混亂。
因此,對於這種情況,建議大家慎用 @@IDENTITY,而儘量採用 SCOPE_IDENTITY() 函式替換之。SCOPE_IDENTITY() 也是得到最後一條自增域的值,但是它是僅限在一個操作範圍之內,而不@@IDENTITY 是取全域性操作的最後一步操作所產生的自增域的值的。
相關文章
- SCOPE_IDENTITY、IDENT_CURRENT 和 @@IDENTITY(zt)IDE
- 在After Insert觸發器中使用INSERT後,影響SCOPE_IDENTITY 問題觸發器IDE
- MASA Auth - SSO與Identity設計IDE
- Asp.Net Core: Swagger 與 Identity Server 4ASP.NETSwaggerIDEServer
- 重置identity值IDE
- Network sniffing and identity authenticationIDE
- .NET8 Identity RegisterIDE
- General->Identity->VersionIDE
- C++:模板的非推斷語境與std::type_identityC++IDE
- SQLServer IDENTITY_INSERT問題SQLServerIDE
- Identity Server 4 - Hybrid Flow - ClaimsIDEServerAI
- 自增長列和序列的區別(identity與sequence的區別)IDE
- asp.net core使用identity+jwt保護你的webapi(一)——identity基礎配置ASP.NETIDEJWTWebAPI
- Microsoft.AspNet.Identity 重置密碼ROSIDE密碼
- HttpContext.User.Identity.IsAuthenticated 為falseHTTPContextIDEFalse
- 深入理解Aspnet Core之Identity(4)IDE
- select @@Identity 返回自增主鍵的值IDE
- 【asp.net core 系列】15 自定義IdentityASP.NETIDE
- C++霧中風景17:模板的非推斷語境與std::type_identityC++IDE
- Establishing SSL connection without server's identity verification is not recommended.ServerIDE
- Identity Server 4 - Hybrid Flow - 保護API資源IDEServerAPI
- .net core Identity整合IdentityServer4 (1)基本操作IDEServer
- Asp.Net Core Identity 多資料庫支援ASP.NETIDE資料庫
- Identity Server 4 預備知識 -- OpenID Connect 簡介IDEServer
- Identity Server 4 預備知識 -- OAuth 2.0 簡介IDEServerOAuth
- Identity Server 4 從入門到落地(十一)—— Docker部署IDEServerDocker
- CIAGAN: Conditional Identity Anonymization Generative Adversarial Networks閱讀筆記IDE筆記
- Identity Server 4 - Hybrid Flow - MVC客戶端身份驗證IDEServerMVC客戶端
- 【asp.net core 系列】13 Identity 身份驗證入門ASP.NETIDE
- gRPC中整合asp.net identity實現oAuth認證RPCASP.NETIDEOAuth
- 從零搭建一個IdentityServer——整合Asp.net core IdentityIDEServerASP.NET
- 學習Identity Server 4的預備知識 (誤刪, 重補)IDEServer
- Identity Server 4 從入門到落地(八)—— .Net Framework 客戶端IDEServerFramework客戶端
- Identity Server 4 從入門到落地(七)—— 控制檯客戶端IDEServer客戶端
- Identity Server 4使用OpenID Connect新增使用者身份驗證(三)IDEServer
- 使用PostMan Canary測試受Identity Server 4保護的Web ApiPostmanIDEServerWebAPI
- .NET 雲原生架構師訓練營(Identity Server)--學習筆記架構IDEServer筆記
- 自開發Web應用和SAP Customer Data Cloud Identity服務的整合WebCloudIDE
- ASP.NET Core3.1使用Identity Server4建立Authorization Server-2ASP.NETIDEServer