一、序列定義
序列(SEQUENCE)是序列號生成器,可以爲表中的行自動生成序列號,產生一組等間隔的數值(類型爲數字)。不佔用磁盤空間,佔用內存。其主要用途是生成表的主鍵值,可以在插入語句中引用,也可以通過查詢檢查當前值,或使序列增至下一個值。
二、創建序列
創建序列需要CREATE SEQUENCE系統權限。序列的創建語法如下:
CREATE SEQUENCE 序列名
[INCREMENT BY n]
[START WITH n]
[{MAXVALUE/ MINVALUE n| NOMAXVALUE}]
[{CYCLE|NOCYCLE}]
[{CACHE n| NOCACHE}];
其中:
1) INCREMENT BY用於定義序列的步長,如果省略,則默認爲1,如果出現負值,則代表Oracle序列的值是按照此步長遞減的。
2) START WITH 定義序列的初始值(即產生的第一個值),默認爲1。
3) MAXVALUE 定義序列生成器能產生的最大值。選項NOMAXVALUE是默認選項,代表沒有最大值定義,這時對於遞增Oracle序列,系統能夠產生的最大值是10的27次方;對於遞減序列,最大值是-1。
4) MINVALUE定義序列生成器能產生的最小值。選項NOMAXVALUE是默認選項,代表沒有最小值定義,這時對於遞減序列,系統能夠產生的最小值是?10的26次方;對於遞增序列,最小值是1。
5) CYCLE和NOCYCLE 表示當序列生成器的值達到限制值後是否循環。CYCLE代表循環,NOCYCLE代表不循環。如果循環,則當遞增序列達到最大值時,循環到最小值;對於遞減序列達到最小值時,循環到最大值。如果不循環,達到限制值後,繼續產生新值就會發生錯誤。
6) CACHE(緩衝)定義存放序列的內存塊的大小,默認爲20。NOCACHE表示不對序列進行內存緩衝。對序列進行內存緩衝,可以改善序列的性能。大量語句發生請求,申請序列時,爲了避免序列在運用層實現序列而引起的性能瓶頸。Oracle序列允許將序列提前生成 cache x個先存入內存,在發生大量申請序列語句時,可直接到運行最快的內存中去得到序列。但cache個數也不能設置太大,因爲在數據庫重啓時,會清空內存信息,預存在內存中的序列會丟失,當數據庫再次啓動後,序列從上次內存中最大的序列號+1 開始存入cache x個。這種情況也能會在數據庫關閉時也會導致序號不連續。
7) NEXTVAL 返回序列中下一個有效的值,任何用戶都可以引用。
8) CURRVAL 中存放序列的當前值,NEXTVAL 應在 CURRVAL 之前指定 ,二者應同時有效。
三、使用序列
調用NEXTVAL將生成序列中的下一個序列號,調用時要指出序列名,即用以下方式調用:
序列名.NEXTVAL
CURRVAL用於產生序列的當前值,無論調用多少次都不會產生序列的下一個值。如果序列還沒有通過調用NEXTVAL產生過序列的下一個值,先引用CURRVAL沒有意義。調用CURRVAL的方法同上,要指出序列名,即用以下方式調用:
序列名.CURRVAL
四、多種序列的創建和使用
(1)最簡單的序列創建:
CREATE SEQUENCE seq_test;
執行這個創建語句會在數據庫中產生一個名字爲seq_test的序列對象,其它的參數都會默認使用默認值。查看生成的源碼如下:
-- Create sequence
create sequence SEQ_TEST
minvalue 1
maxvalue 999999999999999999999999999
start with 1
increment by 1
cache 20;
當你調用seq_test這個序列時,它會爲你產生從1到999999999999999999999999999的連續遞增數值,從1開始,每次增量爲1,不循環產生。產生最大值後將無法使用。默認使用緩存生成,每次緩存的數量爲20個。
(2)創建有最大值的非循環序列
create sequence seq_test1
increment by 1
start with 10
maxvalue 300
minvalue 5;
這個序列雖然設置最小值爲5,但由於開始值爲10,並且不循環產生,所以不會產生10以下的數值。需要注意的是,序列的起始值不能小於最小值,否則創建序列會報錯。我們把上面代碼改成如下:
create sequence seq_test1
increment by 1
start with 10
maxvalue 300
minvalue 11;
SQL> create sequence seq_test1
2 increment by 1
3 start with 10
4 maxvalue 300
5 minvalue 11;
create sequence seq_test1
*
ERROR at line 1:
ORA-04006: START WITH cannot be less than MINVALUE
會提示創建失敗。
(3)創建有最大值的循環序列
create sequence seq_test2
increment by 1
start with 10
maxvalue 300
minvalue 5
cycle ;
當我們執行序列提取到最大值300時,序列會從最小值5開始重新循環生成。而此序列第一次是從開始值生成。需要注意的是,如果是創建一個循環序列,則必須要設定最大值,否則會報錯:
create sequence seq_test2
increment by 1
start with 10
minvalue 5
cycle ;
SQL> create sequence seq_test2
2 increment by 1
3 start with 10
4 minvalue 5
5 cycle ;
create sequence seq_test2
*
ERROR at line 1:
ORA-04015: ascending sequences that CYCLE must specify MAXVALUE
(4)使用帶緩存的序列
創建序列時使用CACHE能提高性能,特別是在高併發的情況下對數據庫的性能提升還是不錯的。但是使用緩存會有產生斷號的現象,如果你的業務要求序列產生的值必須是連續的,那就只能使用nocache了。cache,它的用處是緩存指定個數的序列值。比如你設置的 cache 是20,那麼在獲取 nextval 時,Oracle 會直接從 cache 中取下一個序列值,如果 cache 中緩存的序列值沒有了(比如 cache 中的序列值用完了,或者被手工清空了),那麼 Oracle 會再次產生20個序列值,並放置 cache 中供使用,這樣有助於提高序列值的獲取速度。
--創建一個帶緩存的序列
create sequence SEQ_CACHE
minvalue 1
maxvalue 1000
start with 1
increment by 1
cache 20;
此時執行SEQ_CACHE.nextval 會返回產生第一個值1。調用SEQ_CACHE.currval 查看當前值爲1。
SQL> select SEQ_CACHE.nextval from dual;
NEXTVAL
----------
1
SQL> select SEQ_CACHE.currval from dual;
CURRVAL
----------
1
當我們第一次調用nextval時,由於設置了緩存數爲20,序列會一次生成20個數值放在緩存裏。當我們再次調用nextval時其實是從緩存裏取到的值。假如我們此時將緩存清空再調用nextval,我們來測試一下。
-- 清空 cache 中緩存的序列值
alter system flush shared_pool;
-- 再次調用nextval獲取序列值
select seq_cache.nextval from dual;
發現獲取的值是21而不是2 。因爲緩存裏的值被清空了,所以系統會自動又獲取20個新的連續值放在緩存裏。
SQL> alter system flush shared_pool;
System altered.
SQL> select seq_cache.nextval from dual;
NEXTVAL
----------
21
使用緩存會產生產生的數字不連接的風險,如果系統出異常或oracle重啓則系統會清空緩存的數據,當調用nextval時會重新獲取相應緩存設置的數量的值。
create sequence SEQ_CACHE1
increment by 10
start with 10
maxvalue 300
minvalue 10
cycle
cache 50;
SQL> create sequence SEQ_CACHE1
2 increment by 10
3 start with 10
4 maxvalue 300
5 minvalue 10
6 cycle
7 cache 50;
create sequence SEQ_CACHE1
*
ERROR at line 1:
ORA-04013: number to CACHE must be less than one cycle
我們緩存設定的值是 50,而最大值是 300,那麼爲什麼還會提示這樣的信息呢? 其實我們的 cache 雖然是 50,但是我們每次增長值是 10。這樣 50 次緩存提取出的數是 500 (50*10),我們每次循環的最大值是300,所以就提示我們一次獲取的緩存值必須小於一次循環產生的最大值。
將上面創建序列的語句修改如下:
create sequence SEQ_CACHE1
increment by 10
start with 10
maxvalue 500
minvalue 10
cycle
cache 50;
SQL> create sequence SEQ_CACHE1
2 increment by 10
3 start with 10
4 maxvalue 500
5 minvalue 10
6 cycle
7 cache 50;
create sequence SEQ_CACHE1
*
ERROR at line 1:
ORA-04013: number to CACHE must be less than one cycle
我們一次循環的最大值已經設置成500了,爲什麼還有這樣的錯誤提示?爲什麼還有這樣的錯誤提示?這是因爲還存在一個 minvalue ,minvalue 和 maxvalue 之間是 490 個數,也就是一次循環可以提取 490,但是我們的緩存是500。
create sequence SEQ_CACHE1
increment by 10
start with 10
maxvalue 500
minvalue 9
cycle
cache 50;
發現創建序列成功。在創建序列的時候關於緩存值的設置我們有一個基本的公式要求
最大值-最小值>=(緩存值-1)*每次循環的值
在創建序列時,有如下幾點需要注意,否則序列創建可能不成功。
1、序列第一次必須先調用nextval獲取一個序列值才能使用currval查看當前值
2、序列的起始值不能小於最小值
3、創建一個循環序列,則必須要設定最大值
4、如果創建帶緩存的序列,緩存的值必須滿足約束公式: 最大值-最小值>=(緩存值-1)*每次循環的值
五、修改序列
修改序列的注意事項:
1 必須是序列的擁有者或對序列有 ALTER any sequence權限
2 只有將來的序列值會被改變
3 改變序列的初始值只能通過刪除序列之後重建序列的方法實現
ALTER SEQUENCE emp_sequence INCREMENT BY 10 MAXVALUE 10000 CYCLE;
可以影響Sequence的初始化參數:
SEQUENCE_CACHE_ENTRIES =設置能同時被cache的sequence數目。
六、查詢序列
1 通過數據字典DBA_OBJECTS可以查看用戶擁有的序列。
2 通過數據字典DBA_SEQUENCES可以查看序列的設置。
查看用戶的序列:
SELECT SEQUENCE_NAME,MIN_VALUE,MAX_VALUE,INCREMENT_BY,LAST_NUMBER FROM dba_SEQUENCES;
七、刪除序列
drop sequence sequence_name;
八、序列使用場景
(1). 如果一個事務中只是INSERT時需要序列,其他地方不會需要這個序列,那麼只需要在INSERT ... VALUES (seq.nextval ...)語句中使用即可。
(2). 如果一個事務中INSERT一張表後,還需要插入時的主鍵ID值,作爲外鍵插入其他表,那麼就需要在INSERT第一張表前使用select seq.nextval from dual提前獲取可用的ID保存到一個變量中,爲後面使用。
使用序列時Oracle內部大體是按照如下步驟進行:
(1). 一個序列會被定義到Oracle內部的一張數據字典表(seq$)的一行。
(2). 第一次使用序列,序列的起始值會加上緩存大小,然後更新回行。
(3). Oracle內部會自動跟蹤內存中的兩個值,當前值和目標值。
(4). 每次有回話調用seq.nextval,Oracle會遞增當前值,然後檢查是否超過了目標值,再返回結果。
(5). 如果當前值和目標值相同,Oracle會更新數據字典表中的行,爲目標值加上緩存大小,同時內存中產生了一個新的目標值。
例如create sequence seq cache 20;
名稱爲seq的序列,緩存大小是20,默認初始值是1,步長默認是1。
當使用了一次seq.nextval後,可以看HIGHWATER字段值爲21,即目標值1+緩存大小20=21。
當執行20次後,seq.nextval值變爲21,此時HIGHWATER字段值是41,即目標值21+緩存大小20=41。
也就是每調用seq.nextval值20次,會更新一次seq$表,如果cache值較小,且序列使用的頻率較高,那麼會對seq$表有頻繁的更新操作,日誌量會增加,爲了減少這種情況,我們可以將cache緩存值設置大一些,減少對字典表的更新。