IDENTITY標識列的一些事

2021-05-18 00:13:30 字數 3684 閱讀 7646

identity標識列的一些事

identity(seed , increment)可以定義乙個標識列。seed表示種子值(預設為1),increment表示增量(預設為1)。一張表只能定義乙個標識列。

一.identity列不能保證連續性

identity不能保證標識號是連續的,這是因為如果語句和事務失敗,它們會更改表的當前標識,從而使標識列中的值出現不連貫現象。即使未提交試圖向表中插入值的事務,也永遠無法回滾標識值。例如,如果因 ignore_dup_key 衝突而導致 insert 語句失敗,表的當前標識值仍然會增加。

二.identity列不能保證唯一性

預設情況下,identity列是不能夠手工插入的,但是假如set identity_insert tab on(預設情況下為off),那麼久可以手工插入了,基於此原因,所以identity列也不能保證該列值唯一,所以你要確保該列值唯一,必須使用約束primary key或者unique。

三.identity列在插入後才生成

identity列只有資料真正插入後才生成。基於此原因,若表存在instead of觸發器,那麼在觸發器中的insteaded表中的identity列的值永遠為0。

同時我們若想提前獲取identity也是不可能的,雖然你可以通過dentity_current +increment獲得(下面即將討論到),但是在多使用者的網路環境下這是不可靠的。

四.使用identity()函式插入標識列

只有在select...into 子句中可以使用函式identity新生成乙個標識列:

identity ( data_type [ , seed , increment ] ) as column_name

小提示

在select...into中identity()函式生成的序號是不受order by或top子句控制的。若想生成由order by/top指定的順序,可以先建立乙個包含identity屬性列的新錶,然後使用insert…select(帶order by或top子句)匯入資料就行了。

參考:http://support.microsoft.com/?scid=kb%3ben-us%3b273586&x=5&y=7

五.ident_current

ident_current 返回指定表生成的最新標識值。ident_current 不受作用域和會話的限制,而受限於指定的表。如果對空表或沒有標識列的表呼叫 ident_current 函式,則該函式返回 null。請謹慎使用ident_current 來預報下乙個生成的標識值。由於有其他會話執行的插入,因此實際生成的值可能不同於 ident_current 加上 identity_seed。

六.@@identity和scope_identity

scope_identity 和 @@identity 是在一條 insert、select into 或大容量複製語句(bulk copy)完成後,返回在當前會話中的任何表內所生成的最後乙個標識值。但是,scope_identity 只返回插入到當前作用域中的值;@@identity 不受限於特定的作用域(所謂作用域(scope)是乙個模組:儲存過程、觸發器、函式或批處理。因此,如果兩個語句處於同乙個儲存過程、函式或批處理中,則它們位於相同的作用域中)。和上面的ident_current做個比較總結:

1.如果插入語句未影響任何包含標識列的表,則 @@identity和scope_identity都 返回 null。

2.如果插入了多個行,生成了多個標識值,則 @@identity和scope_identity將返回最後生成的標識值。

3.如果是非插入語句,@@identity和scope_identity值不變。

4.如果語句插入表t1觸發了乙個或多個觸發器(是after觸發器,4同。),該觸發器又執行了生成標識值的插入操作,那麼,在語句執行後立即呼叫 @@identity 將返回觸發器生成的最後乙個標識值。而scope_identity()卻只返回t1表的插入後標識值,即使t1表是巢狀觸發,也只返回直接插入t1後的標識值。

舉例如下:

create table ta(id int identity(1,1))

gocreate trigger tr

on ta

after insert

asbegin

if (select count(*) from ta) < 5 -–不超過5個則巢狀觸發。

insert into ta default values

endgo

insert into ta default values

select @@identity, scope_identity()  --返回5和1

5.如果對包含標識列的表t1執行插入操作後觸發了觸發器,並且觸發器對另乙個沒有標識列的表t2執行了插入操作,則 @@identity 和scope_identity都將將返回第一次插入t1的標識值。

6.出現 insert 或 select into 語句失敗或大容量複製失敗,或者事務被回滾的情況時,@@identity 和scope_identity()值不會恢復為以前的設定。

7.如果語句和事務失敗,它們會更改表的當前標識,從而使標識列中的值出現不連貫現象。即使未提交試圖向表中插入值的事務,也永遠無法回滾標識值。例如,如果因 ignore_dup_key 衝突而導致 insert 語句失敗,表的當前標識值仍然會增加。

七.instead of insert觸發器的情況

當表上建有instead of insert觸發器,對錶的所有插入動作(稱為外部插入),都會被instead of insert觸發器截獲,而真正對錶的插入動作(稱為內部插入)是發生在instead of insert觸發器中的。

因為scope_identity()受作用域影響,因此在外部插入語句後的scope_identity()是不起作用的,都返回null;而 內部插入語句後的scope_identity()卻是起作用的,返回表中標誌列的最後值。

@@identity卻一如既往地發揮作用,返回所有觸發器生成的最後乙個標誌值。

舉例如下:

create table a(id int not null identity(1, 1), code char(10))

gocreate trigger tra

on a

instead of insert

asbegin

select scope_identity()  --返回null

insert into a

select code from inserted

select scope_identity()  --返回id列最後標誌值

endgo

insert into  a

select 'a'

select scope_identity()  --返回null

題外話:在外部insert中使用output字句也不會返回標誌值的,而內部insert中使用output字句卻是可以的。

重置MSSQL的Identity標識列的值

當表中的記錄被全部刪除,但此時標識列的值越來越大的時候,如果不加以重置,它還會無休止的增長。可以用如下語句重置標識列 dbcc checkident table name new reseed value 引數 table name 是要對其當前標識值進行檢查的表名。表名必須符合識別符號規則。有關更...

一些人,一些事,一些

我覺得這是國內it企業浮躁和傳統的官本位性質決定的,導致國內企業都本末倒置。要想改變命運,我覺得有以下出路 1.不做技術了,改做混混 混混的概念很廣泛的,比如銷售 經理 幹部 皮包公司之類其實都屬於這類。中國就是這樣,越浮越掙錢,只有混混才能發財。要不更進一步,做流氓,廣義的流氓,也很不錯。2.專心...

最近的一些事

前段時間,工作不是很忙,閒暇的時候,做了很多自己喜歡做的事情。組內乙個技術很厲害的員工,要離職了,給我們分享了他的很多東西,我們收穫很大。有的同學已經開始自己創業了,想邀請我加入,但是我現在確實還沒有那個信心。自己買了很多書,再一次把自己定位為乙個技術人員,開始堅持不懈的專研技術。身體素質大不如以前...