Sql Server插入數據並返回自增ID,@@IDENTITY,SCOPE_IDENTITY和IDENT_CURRENT的區別


預備知識:SQLServer的IDENTITY關鍵字
IDENTITY關鍵字代表的是一個函數,而不是identity屬性。在access里邊沒有這個函數,所以在access不能用這個語句。語法:identity (數據類型,標識種子,標識增長量)
舉例:select identity (數據類型,標識種子,標識增長量) AS 列名 into 新表 from 原表名

每個表都可以有一個自動增長列,眾所周知的就是IDENTITY列。一個IDENTITY列總是被當作表的主鍵處理(因此,多列主鍵不可能有一個IDENTITY列)。並且從中可看出,我們很容易指定從什么數開始,增幅是多少。

 

SQL SERVER 2000中,有三個比較類似的功能:他們分別是:SCOPE_IDENTITY、IDENT_CURRENT 和 @@IDENTITY,它們都返回插入到 IDENTITY 列中的值。

IDENT_CURRENT 返回為任何會話和任何作用域中的特定表最后生成的標識值。IDENT_CURRENT 不受作用域和會話的限制,而受限於指定的表。IDENT_CURRENT 返回為任何會話和作用域中的特定表所生成的值。
@@IDENTITY 返回為當前會話的所有作用域中的任何表最后生成的標識值。
SCOPE_IDENTITY 返回為當前會話和當前作用域中的任何表最后生成的標識值

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


SQLServer中@@IDENTITY,SCOPE_IDENTITY和IDENT_CURRENT的作用
相同點:
它們都返回插入到IDENTITY列中的值。

不同點:

  A. @@IDENTITY不受作用域(存儲過程、觸發器、函數或批處理)的限制。返回最后一個插入的IDENTITY值。如果在程序中不同的作用域插入的表不同,那么返回最后一個表插入的IDENTITY值。例如:作用域A(存儲過程)在表T1上插入IDENTITY列,而T1上的觸發器會在T2上插入IDENTITY列。則用@@IDENTITY返回T2上插入的IDENTITY值。舉例:
下面的示例向帶有標識列的表中插入一行,並用@@IDENTITY 顯示在新行中使用的標識值。

程序代碼
Insert INTO jobs (job_desc,min_lvl,max_lvl)
VALUES ('Accountant',12,125)
Select @@IDENTITY AS 'Identity'


  B. SCOPE_IDENTITY()受作用域的限制,只返回當前作用域中的最后一個IDENTITY值。上例中,如果在存儲過程中使用SCOPE_IDENTITY(),則返回T1的IDENTITY值。

  C. IDENT_CURRENT()不受作用域的限制,調用它時必須提供表示表名的字符型參數,你可以得到你想要的任何表的最后一個IDENTITY值,即使你的代碼里沒有插入動作。例如:IDENT_CURRENT('T1');

經驗:

比如,表 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 是取全局操作的最后一步操作所產生的自增域的值的。


  根據不同的使用場合,選擇不同的函數。如果在寫存儲過程時,向表中新增了一條數據,需要返回該IDENTITY值,則使用 SCOPE_IDENTITY(),因為它和當前會話相關聯,不會返回一個你不需要的值。如果你僅僅想得到某個IDENTITY列的最后一個值,則使用 IDENT_CURRENT()最方便。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM