1. 程式人生 > >Oracle數據庫序列詳解

Oracle數據庫序列詳解

art term ffffff TP 執行 清空 調用 滿足 sel

前言:

做過web開發的人員基本上都知道,數據庫表中的主鍵值有的時候我們會用數字類型的並且自增。這樣mysql、sql server中的都可以使用工具創建表的時候很容易實現。但是oracle中沒有設置自增的方法,一般情況我們會使用序列和觸發器來實現主鍵自增的功能。下面這面文章主要介紹序列。

一、什麽是序列

序列: Sequence 是oracle提供的用於產生一系列唯一數字的數據庫對象。由於oracle中沒有設置自增列的方法,所以我們在oracle數據庫中主要用序列來實現主鍵自增的功能。

二、怎麽樣創建序列

CREATE SEQUENCE sequence //創建序列名稱
[INCREMENT BY n] //遞增的序列值是 n 如果 n 是正數就遞增,如果是負數就遞減 默認是 1
[START WITH n] //開始的值,遞增默認是 minvalue 遞減是 maxvalue
[{MAXVALUE n | NOMAXVALUE}] //最大值  
[{MINVALUE n | NOMINVALUE}] //最小值
[{CYCLE | NOCYCLE}] //循環/不循環
[{CACHE n | NOCACHE}];//分配並存入到內存中

三、如何使用序列

序列創建後,可以使用序列的NEXTVAL來獲取序列的下一個值,使用CURRVAL來查看當前值。第一次使用必須先使用NEXTVAL來產生一個值後才可以使用CURRVAL進行查看。

//序列調用 產生一個新的序列
select seq_test.nextval from dual
//查看當前序列的值
select seq_test.currval from dual

如果第一次直接使用CURRVAL來訪問序列,就會報如下錯誤:

技術分享圖片

四、創建序列示例

4.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個。關於緩存我們後面再講。

4.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;

執行報錯如下圖:

技術分享圖片

4.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 ;

執行報錯如下圖所示:

技術分享圖片

五、使用帶緩存的序列

創建序列時使用CACHE能提高性能,特別是在高並發的情況下對數據庫的性能提升還是不錯的。但是使用緩存會有產生斷號的現象,如果你的業務要求序列產生的值必須是連續的,那就只能使用nocache了。

我們先來了解一下cache這個參數的作用。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。

當我們第一次調用nextval時,由於設置了緩存數為20,序列會一次生成20個數值放在緩存裏。當我們再次調用nextval時其實是從緩存裏取到的值。假如我們此時將緩存清空再調用nextval,我們來測試一下。

-- 清空 cache 中緩存的序列值
alter system flush shared_pool;
-- 再次調用nextval獲取序列值
select seq_cache.nextval from dual;

發現獲取的值是21而不是2 。因為緩存裏的值被清空了,所以系統會自動又獲取20個新的連續值放在緩存裏。

我們現在再執行四次nextval,會得到當前的值為25。此時我們再次清空緩存,然後再次調用nextval來獲取序列。

-- 清空 cache 中緩存的序列值
alter system flush shared_pool;
-- 再次調用nextval獲取序列值
select seq_cache.nextval from dual;

我們會得到當前的值為41。為什麽呢?因為每次oracle獲取20值是從上次獲取的最大值開始的,而不是從當前值開始計算的!使用緩存會產生產生的數字不連接的風險,如果系統出異常或oracle重啟則系統會清空緩存的數據,當調用nextval時會重新獲取相應緩存設置的數量的值。

我們再來看一個帶緩存的案例:

create sequence SEQ_CACHE1
increment by 10
start with 10
maxvalue 300
minvalue 10
cycle
cache 50;

執行後出錯如下:

技術分享圖片

為什麽會出現這樣的錯誤呢?

我們緩存設定的值是 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;

發現仍然報錯如下圖所示:

技術分享圖片

這又是為什麽呢?我們一次循環的最大值已經設置成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)*每次循環的值

以上是對oracle數據庫的序列的詳細介紹,希望能對大家理解和掌握序列的使用有所幫助。

Oracle數據庫序列詳解