Oracle序列號
序列號SEQUENCE:是Oracle提供的用於產生一系列唯一數字的資料庫物件。
序列號在資料庫中是一個共享物件, 序列號是一個計數器,它並不會與特定的表關聯。
主要用於提供主鍵值或唯一約束值。
將序列值裝入記憶體可以提高訪問效率。
建立序列號語法:
CREATE SEQUENCE [SCHEMA.]SEQUENCE_NAME
[INCREMENT BY N]
[START WITH N]
[{MAXVALUE N | NOMAXVALUE}]
[{MINVALUE N | NOMINVALUE}]
[{CYCLE | NOCYCLE}]
[{CACHE N | NOCACHE}];
SEQUENCE_NAME:序列號名稱
INCREMENT BY用於定義序列的步長,如果省略,則預設為1,如果出現負值,則代表Oracle序列的值是按照此步長遞減的。
START WITH 定義序列的初始值(即產生的第一個值),預設為1。
MAXVALUE 定義序列生成器能產生的最大值。選項NOMAXVALUE是預設選項,代表沒有最大值定義,這時對於遞增Oracle序列,系統能夠產生的最大值是10的27次方;對於遞減序列,最大值是-1。
MINVALUE定義序列生成器能產生的最小值。選項NOMAXVALUE是預設選項,代表沒有最小值定義,這時對於遞減序列,系統能夠產生的最小值是-10的26次方;對於遞增序列,最小值是1。
CYCLE和NOCYCLE 表示當序列生成器的值達到限制值後是否迴圈。CYCLE代表迴圈,NOCYCLE代表不迴圈。如果迴圈,則當遞增序列達到最大值時,迴圈到最小值;最小值為1。對於遞減序列達到最小值時,迴圈到最大值。如果不迴圈,達到限制值後,繼續產生新值就會發生錯誤。
CACHE(緩衝)定義存放序列的記憶體塊的大小,預設為20。NOCACHE表示不對序列進行記憶體緩衝。對序列進行記憶體緩衝,可以改善序列的效能。 快取選項會造成資料丟失,當例項異常關閉時。
如果指定CACHE值,ORACLE就可以預先在記憶體裡面放置一些SEQUENCE,這樣存取的快些。CACHE裡面的取完後,ORACLE自動再取一組到CACHE。使用CACHE或許會跳號, 比如資料庫突然不正常DOWN掉(SHUTDOWN ABORT),CACHE中的SEQUENCE就會丟失。舉個例子:比如你的SEQUENCE中CACHE 100,那當你SEQUENCE取到90時突然斷電,那麼在你重啟資料庫後,SEQUENCE的值將從101開始。
如果指定NOCACHE值,ORACLE就不會預先在記憶體裡面存放SEQUENCE,當然這也就可以避免資料庫不正常DOWN掉的SEQUENCE丟失。不過會產生一些問題:建立NOCACHE SEQUENCE在高併發訪問時,容易導致ROW CACHE LOCK等待事件,主要原因是每次獲取NEXTVAL時都需要修改ROWCACHE中的字典資訊。使用NOCACHE SEQUENCE,還會導致如下問題:
由於每次修改字典資訊都需要COMMIT,可能導致LOG FILE SYNC等待,NOCACHE SEQUENCE在RAC環境下,會對基於SEQUENCE生成的列建立的索引,造成例項間大量索引塊爭用,基於以上問題,避免建立NOCACHE SEQUENCE。
SEQUENCE相關保護機制:
ROW CACHE LOCK:在呼叫SEQUENCE.NEXTVAL情況下需要修改資料字典時發生,對應ROW CACHE LOCK事件。
SQ LOCK:在記憶體快取(並非ROW CACHE)上獲取SEQUENCE.NEXTVAL時發生,對應ENQ:SQ-CONTENTION事件。
SV LOCK:RAC環境下獲取CACHE+ORDER屬性的SEQUENCE.NEXTVAL時發生,對應DFS LOCK HANDLE事件。
使用序列號會產生跳號,序列在下列情況下出現裂縫:
回滾
系統異常
多個表同時使用同一序列
序列號使用:
-- 返回序列中下一個有效的值,任何使用者都可以引用
SELECT SEQUENCE_NAME.NEXTVAL FROM DUAL;
-- 序列的當前值
SELECT SEQUENCE_NAME.CURRVAL FROM DUAL;
例項應用:實現ID的自動遞增
建立序列號
CREATE SEQUENCE TEST_SEQ INCREMENT BY 1 START WITH 1 MAXVALUE 30000 MINVALUE 1
CACHE 2;
建立表
CREATE TABLE TEST_TABLE(
ID NUMBER(6),
NAME VARCHAR2(30),
CONSTRAINT PK_ID PRIMARY KEY(ID)
);
插入資料
INSERT INTO TEST_TABLE VALUES(TEST_SEQ.NEXTVAL,'TOM');
COMMIT;
檢視資料庫中的序列號:
SELECT * FROM USER_SEQUENCES;
SELECT * FROM ALL_SEQUENCES;
SELECT * FROM DBA_SEQUENCES;
修改序列號:
ALTER SEQUENCE SEQUENCE_NAME
[INCREMENT BY N]
[{MAXVALUE N | NOMAXVALUE}]
[{MINVALUE N | NOMINVALUE}]
[{CYCLE | NOCYCLE}]
[{CACHE N | NOCACHE}];
不能修改序列的初始值,否則會報ORA-02283:無法更改啟動序列號
刪除序列號:
DROP SEQUENCE [SCHEMA.]序列名;