在 Oracle 中實(shí)現(xiàn)自增ID

如果你經(jīng)常使用 MySQL霜瘪,你肯定對 AUTO_INCREMENT 非常熟悉,因?yàn)榻?jīng)常要用到它惧磺。

一颖对、什么是自增列?

自增列是數(shù)據(jù)庫中值隨插入的每個(gè)行自動(dòng)增加的一列磨隘。它最常用于主鍵或 ID 字段缤底,這樣每次增加一行時(shí),不用指該字段的值番捂,它就會(huì)自動(dòng)增加个唧,而且是唯一的。

當(dāng)在 MySQL 中定義列時(shí)白嘁,我們可以指定一個(gè)名為 AUTO_INCREMENT 的參數(shù)坑鱼。然后膘流,每當(dāng)將新值插入此表中時(shí)絮缅,放入此列的值比最后一個(gè)值加 1。

但很不幸呼股,Oracle 沒有 AUTO_INCREMENT 功能耕魄。 那要如何在Oracle中做到這一點(diǎn)呢?

二彭谁、在 Oracle 11g 中設(shè)置自增字段

1. 創(chuàng)建表

首先創(chuàng)建一張用于測試的表:

CREATE TABLE "TEST" (
    ID NUMBER(11) PRIMARY KEY,
    NAME VARCHAR2(50BYTE) NOT NULL
);
2. 創(chuàng)建序列

然后創(chuàng)建一個(gè)名為 TEST_ID_SEQ 的序列(序列名稱自己隨意設(shè)定):

CREATE SEQUENCE TEST_ID_SEQ
INCREMENT BY 1
START WITH 100
MAXVALUE 999999999
NOCYCLE
NOCACHE;

如果要?jiǎng)h除序列吸奴,可以使用下面的 SQL 命令:

DROP SEQUENCE TEST_ID_SEQ;

對 SEQUENCE 的一些說明:

  • INCREMENT BY 用于指定序列增量(默認(rèn)值:1),如果指定的是正整數(shù)缠局,則序列號(hào)自動(dòng)遞增则奥,如果指定的是負(fù)數(shù),則自動(dòng)遞減狭园。
  • START WITH 用于指定序列生成器生成的第一個(gè)序列號(hào)读处,當(dāng)序列號(hào)順序遞增時(shí)默認(rèn)值為序列號(hào)的最小值,當(dāng)序列號(hào)順序遞減時(shí)默認(rèn)值為序列號(hào)的最大值唱矛。
  • MAXVALUE 用于指定序列生成器可以生成的組大序列號(hào)(必須大于或等于 START WITH罚舱,并且必須大于 MINVALUE),默認(rèn)為 NOMAXVALUE绎谦。
  • MINVALUE 用于指定序列生成器可以生成的最小序列號(hào)(必須小于或等于 START WITH管闷,并且必須小于 MAXVALUE),默認(rèn)值為 NOMINVALUE窃肠。
  • CYCLE 用于指定在達(dá)到序列的最大值或最小值之后是否繼續(xù)生成序列號(hào)包个,默認(rèn)為 NOCYCLE。
  • CACHE 用于指定在內(nèi)存中可以預(yù)分配的序列號(hào)個(gè)數(shù)(默認(rèn)值:20)冤留。

到這一步其實(shí)就已經(jīng)可以實(shí)現(xiàn)字段自增碧囊,只要插入的時(shí)候恃锉,將 ID 的值設(shè)置為序列的下一個(gè)值 TEST_ID_SEQ.NEXTVAL 就可以了:

SQL> INSERT INTO "TEST" ("ID", "NAME") VALUES (TEST_ID_SEQ.NEXTVAL, 'name1');
SQL> INSERT INTO "TEST" ("ID", "NAME") VALUES (TEST_ID_SEQ.NEXTVAL, 'name2');
SQL> INSERT INTO "TEST" ("ID", "NAME") VALUES (TEST_ID_SEQ.NEXTVAL, 'name3');
SQL> SELECT * FROM "TEST";

ID   NAME
---  ------
100 name1
101 name2
102 name3

為了簡化插入操作,我們還可以創(chuàng)建一個(gè)觸發(fā)器呕臂,當(dāng)將數(shù)據(jù)插入到 "TEST" 表的時(shí)候破托,自動(dòng)將最新的 ID 插入進(jìn)去。

3. 創(chuàng)建觸發(fā)器
CREATE OR REPLACE TRIGGER TEST_ID_SEQ_TRG
BEFORE INSERT ON "TEST"
FOR EACH ROW
WHEN (NEW."ID" IS NULL)
BEGIN
  SELECT TEST_ID_SEQ.NEXTVAL
  INTO :NEW."ID"
  FROM DUAL;
END;

這樣的話歧蒋,每次寫插入語句土砂,只需要將 ID 字段的值設(shè)置為 NULL 它就會(huì)自動(dòng)遞增了:

SQL> INSERT INTO "TEST" ("ID", "NAME") VALUES (NULL, 'name4');
SQL> INSERT INTO "TEST" ("ID", "NAME") VALUES (NULL, 'name5');
SQL> INSERT INTO "TEST" ("ID", "NAME") VALUES (NULL, 'name6');
SQL> SELECT * FROM "TEST";

ID   NAME
---  ------
100 name1
101 name2
102 name3
103 name4
104 name5
105 name6
4. 一些值得注意的地方
4.1 插入指定 ID

如果某條插入語句指定了 ID 的值如:

SQL> INSERT INTO "TEST" ("ID", "NAME") VALUES (1000, 'name1001');
SQL> SELECT * FROM "TEST";

ID   NAME
---  ------
100 name1
101 name2
102 name3
103 name4
104 name5
1000    name1001

那么下次 ID 還是會(huì)在原來的基礎(chǔ)上繼續(xù)增加:

SQL> INSERT INTO "TEST" ("ID", "NAME") VALUES (NULL, 'name1001');
SQL> SELECT * FROM "TEST";

ID   NAME
---  ------
100 name1
101 name2
102 name3
103 name4
104 name5
1000    name1001

但當(dāng)序列的值到了 1000 的時(shí)候,如果 ID 允許重復(fù)谜洽,就會(huì)有兩行記錄 ID 都為 1000萝映。

但如果 ID 設(shè)置為了主鍵,如本文的例子 ID NUMBER(11) PRIMARY KEY阐虚,則插入就會(huì)報(bào)錯(cuò):

Error : ORA-00001: unique constraint (SOFTWARE.SYS_C0014995) violated
4.2 字段加引號(hào)

在 SQL 語句中序臂,字段最好都加上引號(hào),不然可能會(huì)報(bào)錯(cuò):

Error : ORA-00900: invalid SQL statement

或:

ORA-24344: Success with Compilation Error
4.3 SQUENCE
  • 第一次 NEXTVAL 返回的是初始值实束;隨后的 NEXTVAL 會(huì)自動(dòng)增加 INCREMENT BY 對應(yīng)的值奥秆,然后返回增加后的值。
  • CURRVAL 總是返回當(dāng)前 SEQUENCE 的值咸灿,但是在第一次 NEXTVAL 初始化之后才能使用 CURRVAL 构订,否則會(huì)出錯(cuò)。
  • 一次 NEXTVAL 會(huì)增加一次 SEQUENCE 的值避矢,所以如果在同一個(gè)語句里面使用多個(gè)NEXTVAL悼瘾,其值就是不一樣的。
  • 如果指定 CACHE 值审胸,Oracle 就可以預(yù)先在內(nèi)存里面放置一些 SEQUENCE亥宿,這樣存取的快些。 CACHE 里面的取完后砂沛,Oracle 自動(dòng)再取一組到 CACHE烫扼。
  • 但使用 CACHE 或許會(huì)跳號(hào),比如數(shù)據(jù)庫突然不正常關(guān)閉(shutdown abort)尺上, CACHE 中的 SEQUENCE 就會(huì)丟失材蛛。所以可以在 CREATE SEQUENCE 的時(shí)候用 NOCACHE 防止這種情況。
4.4 性能

在數(shù)據(jù)庫操作中怎抛,觸發(fā)器的使用耗費(fèi)系統(tǒng)資源相對較大卑吭。如果對于表容量相對較小的表格我們可以忽略觸發(fā)器帶來的性能影響。

考慮到大表操作的性能問題马绝,需要盡可能的減少觸發(fā)器的使用豆赏。對于以上操作,就可以拋棄觸發(fā)器的使用,直接手動(dòng)調(diào)用序列函數(shù)即可掷邦,但這樣可能在程序維護(hù)上稍微帶來一些不便白胀。

三、實(shí)現(xiàn)自增ID,實(shí)現(xiàn)步驟順序總結(jié)

  1. 創(chuàng)建ID為主鍵的表(PRIMARY KEY)
  2. 創(chuàng)建序列
  3. 創(chuàng)建觸發(fā)器
  4. 每個(gè)表都需要按順序123建一次抚岗,工程量浩大

四或杠、在 Oracle 12c 中設(shè)置自增字段

在 Oracle 12c 中設(shè)置自增字段就簡單多了,因?yàn)?ORacle 12c 提供了 IDENTITY 屬性:

CREATE TABLE "TEST" (
    ID NUMBER(11) GENERATED BY DEFAULT ON NULL AS IDENTITY,
    NAME VARCHAR2(50BYTE) NOT NULL
);

這樣就搞定了宣蔚!和 MySQL 一樣簡單向抢!??????

五、總結(jié)

所以如上所屬胚委,在 Oracle 中設(shè)置自增字段挟鸠,需要根據(jù)不同的版本使用不同的方法:

在 Oracle 11g 中,需要先創(chuàng)建序列(SQUENCE)再創(chuàng)建一個(gè)觸發(fā)器(TRIGGER)亩冬。
在 Oracle 12c 中艘希,只需要使用 IDENTITY 屬性就可以了。

參考文檔:

oracle 實(shí)現(xiàn) 自增主鍵功能

在 Oracle 中設(shè)置自增列

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末硅急,一起剝皮案震驚了整個(gè)濱河市覆享,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌铜秆,老刑警劉巖淹真,帶你破解...
    沈念sama閱讀 211,948評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異连茧,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)巍糯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評論 3 385
  • 文/潘曉璐 我一進(jìn)店門啸驯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人祟峦,你說我怎么就攤上這事罚斗。” “怎么了宅楞?”我有些...
    開封第一講書人閱讀 157,490評論 0 348
  • 文/不壞的土叔 我叫張陵针姿,是天一觀的道長。 經(jīng)常有香客問我厌衙,道長距淫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,521評論 1 284
  • 正文 為了忘掉前任婶希,我火速辦了婚禮榕暇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己彤枢,他們只是感情好狰晚,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著缴啡,像睡著了一般壁晒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上业栅,一...
    開封第一講書人閱讀 49,842評論 1 290
  • 那天讨衣,我揣著相機(jī)與錄音,去河邊找鬼式镐。 笑死反镇,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的娘汞。 我是一名探鬼主播歹茶,決...
    沈念sama閱讀 38,997評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼你弦!你這毒婦竟也來了惊豺?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,741評論 0 268
  • 序言:老撾萬榮一對情侶失蹤禽作,失蹤者是張志新(化名)和其女友劉穎尸昧,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體旷偿,經(jīng)...
    沈念sama閱讀 44,203評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡烹俗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了萍程。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片幢妄。...
    茶點(diǎn)故事閱讀 38,673評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖茫负,靈堂內(nèi)的尸體忽然破棺而出蕉鸳,到底是詐尸還是另有隱情,我是刑警寧澤忍法,帶...
    沈念sama閱讀 34,339評論 4 330
  • 正文 年R本政府宣布潮尝,位于F島的核電站,受9級特大地震影響饿序,放射性物質(zhì)發(fā)生泄漏勉失。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評論 3 313
  • 文/蒙蒙 一嗤堰、第九天 我趴在偏房一處隱蔽的房頂上張望戴质。 院中可真熱鬧度宦,春花似錦、人聲如沸告匠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽后专。三九已至划鸽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間戚哎,已是汗流浹背裸诽。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留型凳,地道東北人丈冬。 一個(gè)月前我還...
    沈念sama閱讀 46,394評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像甘畅,于是被迫代替她去往敵國和親埂蕊。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評論 2 349

推薦閱讀更多精彩內(nèi)容