SQL查詢 [SCOPE_IDENTITY、IDENT_CURRENT 和 @@IDENTITY的區別(比較)] ---轉載

@@IDENTITY (Transact-SQL) 返回最後插入的標識值的系統函數。服務器

備註 在一條 INSERT、SELECT INTO 或大容量複製語句完成後,@@IDENTITY 中包含語句生成的最後一個標識值。若是語句未影響任何包含標識列的表,則 @@IDENTITY 返回 NULL。若是插入了多個行,生成了多個標識值,則 @@IDENTITY 將返回最後生成的標識值。若是語句觸發了一個或多個觸發器,該觸發器又執行了生成標識值的插入操做,那麼,在語句執行後當即調用 @@IDENTITY 將返回觸發器生成的最後一個標識值。若是對包含標識列的表執行插入操做後觸發了觸發器,而且觸發器對另外一個沒有標識列的表執行了插入操做,則 @@IDENTITY 將返回第一次插入的標識值。出現 INSERT 或 SELECT INTO 語句失敗或大容量複製失敗,或者事務被回滾的狀況時,@@IDENTITY 值不會恢復爲之前的設置。session

@@IDENTITY 函數的做用域是執行該函數的本地服務器上的當前會話。此函數不能應用於遠程或連接服務器。若要得到其餘服務器上的標識值,請在遠程服務器或連接服務器上執行存儲過程,並使(在遠程或連接服務器的環境中執行的)該存儲過程收集標識值,並將其返回本地服務器上的發出調用的鏈接。函數

附:使用@IDENTITY基本知識post

1. IDENTITY 列不能由用戶直接更新,它是由系統自動維護的。 2.該列數據類型必須爲數值型:int, smallint, tinyint, decimal or numeric with scale 0。 3.該列不能爲 null。 4.不能在該列上設置缺省值。
5.遞增量只能爲整形(好比:1,2,-3)。不能爲小數,也不能爲0。 6.基值(種子值 seed)能夠由用戶設置,缺省值爲1。this

@@IDENTITY 是當前鏈接的全局變量,只對當前鏈接有效。也就是說,若是斷開鏈接再從新鏈接後,@@IDENTITY 爲 null。以 ADO 來講,@@IDENTITY 在 Connection 對象打開和關閉期間是有意義的,即在 Connection 對象的存在範圍內有效。在 MTS 組件中,從打開鏈接到顯式的關閉鏈接(Connection.Close)或者到調用了 SetAbort,SetComplete以前,在這期間,@@IDENTITY 有意義。 使用 Truncate table 語句會使 IDENTITY 列從新開始計算。 對象

【IDENT_CURRENT (Transact-SQL)】blog

IDENT_CURRENT (Transact-SQL) 返回爲某個會話和做用域中指定的表或視圖生成的最新的標識值。 事務

語法:IDENT_CURRENT( 'table_name' ) 參數table_name 其標識值被返回的表的名稱。table_name 的數據類型爲 varchar,無默認值。ip

備註 IDENT_CURRENT 不受做用域和會話的限制,而受限於指定的表。 IDENT_CURRENT 返回爲任何會話和做用域中的特定表所生成的值。 在空表中調用 IDENT_CURRENT 函數時,此函數將返回 NULL。ci

 

【SCOPE_IDENTITY (Transact-SQL)】

SCOPE_IDENTITY (Transact-SQL)  返回插入到同一做用域中的標識列內的最後一個標識值。 一個範圍是一個模塊:存儲過程、觸發器、函數或批處理。所以,若是兩個語句處於同一個存儲過程、函數或批處理中,則它們位於相同的做用域中。

語法:SCOPE_IDENTITY()

備註

SCOPE_IDENTITY 和 @@IDENTITY 返回在當前會話中的任何表內所生成的最後一個標識值。可是,SCOPE_IDENTITY 只返回插入到當前做用域中的值;@@IDENTITY 不受限於特定的做用域。

例如,有兩個表 T1 和 T2,而且在 T1 上定義了 INSERT 觸發器。當將某行插入 T1 時,觸發器被激發,並在 T2 中插入一行。 該方案演示了兩個做用域:在 T1 上的插入,以及在 T2 經過觸發器的插入。

假設 T1 和 T2 都有標識列,@@IDENTITY 和 SCOPE_IDENTITY 將在 T1 上的 INSERT 語句的最後返回不一樣的值。@@IDENTITY 將返回在當前會話中的任何做用域內插入的最後一個標識列的值。這是在 T2 中插入的值。SCOPE_IDENTITY() 將返回在 T1 中插入的 IDENTITY 值。這是在同一個做用域內發生的最後的插入。若是在任何 INSERT 語句做用於做用域中的標識列以前調用 SCOPE_IDENTITY() 函數,則該函數將返回空值。

【總結】

@@IDENTITY、SCOPE_IDENTITY 和 IDENT_CURRENT 是類似的函數,由於他們都返回插入到表的 IDENTITY 列的最後一個值。 這三個函數都返回最後生成的標識值。可是,上述每一個函數中定義的「最後」的做用域和會話有所不一樣。 IDENT_CURRENT 返回爲某個會話和用域中的指定表生成的最新標識值。 @@IDENTITY 返回爲跨全部做用域的當前會話中的某個表生成的最新標識值。 SCOPE_IDENTITY 返回爲當前會話和當前做用域中的某個表生成的最新標識值。

@@IDENTITY 和 SCOPE_IDENTITY 能夠返回當前會話中的全部表中生成的最後一個標識值。可是,SCOPE_IDENTITY 只在當前做用域內返回值,而 @@IDENTITY 不限於特定的做用域。IDENT_CURRENT 不受做用域和會話的限制,而受限於指定的表。IDENT_CURRENT 能夠返回任何會話和任何做用域中爲特定表生成的標識值。

若是語句和事務失敗,它們會更改表的當前標識,從而使標識列中的值出現不連貫現象。即便未提交試圖向表中插入值的事務,也永遠沒法回滾標識值。例如,若是因 IGNORE_DUP_KEY 衝突而致使 INSERT 語句失敗,表的當前標識值仍然會增長。

 

【Tips】 例如,有兩個表 T1 和 T2,在 T1 上定義了一個 INSERT 觸發器。當將某行插入 T1 時,觸發器被激發,並在 T2 中插入一行。此例說明了兩個做用域:一個是在 T1 上的插入,另外一個是做爲觸發器的結果在 T2 上的插入。

假設 T1 和 T2 都有 IDENTITY 列,@@IDENTITY 和 SCOPE_IDENTITY 將在 T1 上的 INSERT 語句的最後返回不一樣的值。

@@IDENTITY 返回插入到當前會話中任何做用域內的最後一個 IDENTITY 列值,該值是插入 T2 中的值。

SCOPE_IDENTITY() 返回插入 T1 中的 IDENTITY 值,該值是發生在相同做用域中的最後一個 INSERT。若是在做用域中發生插入語句到標識列以前喚醒調用 SCOPE_IDENTITY() 函數,則該函數將返回 NULL 值。而IDENT_CURRENT('T1') 和 IDENT_CURRENT('T2') 返回的值分別是這兩個表最後自增的值。

【Example】 也許你們對SQL Server中的 @@IDENTITY 都不陌生,都知道它是獲取數據表中最後一條插入數據的IDENTITY值。好比,表 A 中有個 ID 爲自增1的字段,假設此時 ID 的值爲100,如今若是我往表A插入一條數據,並在插入後 SELECT @@IDENTITY,則其返回 101,最後一條IDENTITY域(即ID域)的值。 如今問題來了,爲何說要慎用@@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 是取全局操做的最後一步操做所產生的自增域的值的。

示例

如下示例將顯示由 IDENT_CURRENT、@@IDENTITY 和 SCOPE_IDENTITY 返回的不一樣標識值。

USE AdventureWorks; GO DROP TABLE t6; DROP TABLE t7; GO CREATE TABLE t6(id int IDENTITY); CREATE TABLE t7(id int IDENTITY(100,1)); GO CREATE TRIGGER t6ins ON t6 FOR INSERT
AS BEGIN    INSERT t7 DEFAULT VALUES END; GO --End of trigger definition

SELECT   * FROM t6; --id is empty.

SELECT   * FROM t7; --ID is empty.

--Do the following in Session 1 INSERT t6 DEFAULT VALUES; SELECT @@IDENTITY; /*Returns the value 100. This was inserted by the trigger.*/

SELECT SCOPE_IDENTITY(); /* Returns the value 1. This was inserted by the
INSERT statement two statements before this query.*/

SELECT IDENT_CURRENT('t7'); /* Returns value inserted into t7, that is in the trigger.*/

SELECT IDENT_CURRENT('t6'); /* Returns value inserted into t6. This was the INSERT statement four statements before this query.*/

-- Do the following in Session 2. SELECT @@IDENTITY; /* Returns NULL because there has been no INSERT action up to this point in this session.*/

SELECT SCOPE_IDENTITY(); /* Returns NULL because there has been no INSERT action up to this point in this scope in this session.*/

SELECT IDENT_CURRENT('t7'); /* Returns the last value inserted into t7.

相關文章
相關標籤/搜索