Oracle列自增實現(2)-Identity Columns in Oracle Database 12c Release 1 (12.1)


Oracle列自增-Identity Columns in Oracle Database 12c Release 1 (12.1)

在ORACLE 12C以前的版本中,如果要實現列自增長,需要通過序列+觸發器實現,到了12C ORACLE 引進了Identity Columns新特性,從而實現了列自增長功能。

一、Identity Columns使用語法

GENERATED

[ ALWAYS | BY DEFAULT [ ON NULL ] ]

AS IDENTITY [ ( identity_options ) ]identity_options

二、identity_clause

clip_image001

2.1 ALWAYS選項

DROP TABLE IDENTITY_TEST_TAB PURGE;

CREATE TABLE identity_test_tab (

id NUMBER GENERATED ALWAYS AS IDENTITY,

description VARCHAR2(30)

);

插入測試1:

INSERT INTO identity_test_tab (description) VALUES ('Just DESCRIPTION')

[SQL]INSERT INTO identity_test_tab (description) VALUES ('Just DESCRIPTION')

受影響的行: 1

時間: 0.008s

插入測試2:

INSERT INTO identity_test_tab (id, description) VALUES (NULL, 'ID=NULL and DESCRIPTION')

[SQL]INSERT INTO identity_test_tab (id, description) VALUES (NULL, 'ID=NULL and DESCRIPTION')

[Err] ORA-32795: cannot insert into a generated always identity column 無法插入到“始終生成”身份列

插入測試3:

INSERT INTO identity_test_tab (id, description) VALUES (999, 'ID=999 and DESCRIPTION')

[SQL]INSERT INTO identity_test_tab (id, description) VALUES (999, 'ID=999 and DESCRIPTION')

[Err] ORA-32795: cannot insert into a generated always identity column

clip_image002

更新測試:

UPDATE IDENTITY_TEST_TAB SET ID=2 WHERE ID=1

[SQL]UPDATE IDENTITY_TEST_TAB SET ID=2 WHERE ID=1

[Err] ORA-32796: cannot update a generated always identity column

結論:

  1. GENERATED ALWAYS AS IDENTITY 可以不指定該列進行插入
  2. GENERATED ALWAYS AS IDENTITY不能在該列中插入NULL值
  3. GENERATED ALWAYS AS IDENTITY不能指定具體值插入
  4. GENERATED ALWAYS AS IDENTITY 不能使用update更新該列

2.2 BY DEFAULT選項

DROP TABLE identity_test_tab PURGE;

CREATE TABLE identity_test_tab (

id NUMBER GENERATED BY DEFAULT AS IDENTITY,

description VARCHAR2(30)

);

插入測試1:

INSERT INTO identity_test_tab (description) VALUES ('Just DESCRIPTION');

[SQL]INSERT INTO identity_test_tab (id, description) VALUES (999, 'ID=999 and DESCRIPTION')

受影響的行: 1

時間: 0.001s

SELECT * FROM identity_test_tab;

clip_image0021

插入測試2:

INSERT INTO identity_test_tab (id, description) VALUES (999, 'ID=999 and DESCRIPTION');

[SQL]INSERT INTO identity_test_tab (id, description) VALUES (999, 'ID=999 and DESCRIPTION')

受影響的行: 1

時間: 0.001s

SELECT * FROM identity_test_tab;

clip_image003

插入測試3:

INSERT INTO identity_test_tab (id, description) VALUES (NULL, 'ID=NULL and DESCRIPTION');

[SQL]INSERT INTO identity_test_tab (id, description) VALUES (NULL, 'ID=NULL and DESCRIPTION')

[Err] ORA-01400: cannot insert NULL into ("TEST_USER"."IDENTITY_TEST_TAB"."ID")

clip_image003

更新測試:

UPDATE IDENTITY_TEST_TAB SET ID=2 WHERE ID=1

[SQL]UPDATE IDENTITY_TEST_TAB SET ID=2 WHERE ID=1

受影響的行: 1

時間: 0.001sUPDATE IDENTITY_TEST_TAB SET ID=2 WHERE ID=1

     結論:

  1. GENERATED BY DEFAULT AS IDENTITY 可以不指定該列進行插入
  2. GENERATED BY DEFAULT AS IDENTITY 可以指定具體值插入
  3. GENERATED BY DEFAULT AS IDENTITY 不能在該列中插入null值
  4. 可以使用update更新該列,但不能更新為NULL

2.3 DEFAULT ON NULL選項

DROP TABLE identity_test_tab PURGE;

CREATE TABLE identity_test_tab (

id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY,

description VARCHAR2(30)

);

插入測試:

INSERT INTO identity_test_tab (description) VALUES ('Just DESCRIPTION');

INSERT INTO identity_test_tab (id, description) VALUES (999, 'ID=999 and DESCRIPTION');

INSERT INTO identity_test_tab (id, description) VALUES (NULL, 'ID=NULL and DESCRIPTION');

[SQL]INSERT INTO identity_test_tab (description) VALUES ('Just DESCRIPTION')

受影響的行: 1

時間: 0.003s

[SQL]INSERT INTO identity_test_tab (id, description) VALUES (999, 'ID=999 and DESCRIPTION')

受影響的行: 1

時間: 0.001s

[SQL]INSERT INTO identity_test_tab (id, description) VALUES (NULL, 'ID=NULL and DESCRIPTION')

受影響的行: 1

時間: 0.002s

SELECT * FROM identity_test_tab;

clip_image004

更新測試

UPDATE IDENTITY_TEST_TAB SET ID=3 WHERE ID=1

[SQL]UPDATE IDENTITY_TEST_TAB SET ID=3 WHERE ID=1

受影響的行: 1

時間: 0.004s

     結論:

  1. GENERATED BY DEFAULT ON NULL AS IDENTITY 可以不指定該列進行插入
  2. GENERATED BY DEFAULT ON NULL AS IDENTITY 方式可以指定具體值插入
  3. GENERATED BY DEFAULT ON NULL AS IDENTITY 可以在該列中插入null值
  4. 可以使用update更新該列

三、原理

3.1 Identity Columns 是基於序列實現的

使用此語法實現ID自增,要求必須有創建序列的權限。可以推測是基於序列實現的

執行完建表語句后:

CREATE TABLE identity_test_tab (

id NUMBER GENERATED ALWAYS AS IDENTITY,

description VARCHAR2(30)

);

查看user_objects

SELECT object_name, object_type FROM user_objects;

clip_image005

發現建表的時候自動生成了一個sequence

SELECT table_name, 

column_name,

generation_type,

identity_options

FROM all_tab_identity_cols

WHERE owner = 'TEST_USER';

clip_image006

表和sequence的關系存在SYS.IDNSEQ$表中

Sys登陸查看

SELECT a.name AS table_name,

b.name AS sequence_name

FROM sys.idnseq$ c

JOIN obj$ a ON c.obj# = a.obj#

JOIN obj$ b ON c.seqobj# = b.obj#

where a.name='IDENTITY_TEST_TAB';

clip_image007

3.2 GENERATED IDENTITY 中sequence不能單獨被刪除

DROP TABLE IDENTITY_TEST_TAB

刪除表后,該sequence還存在。且該sequence無法被刪除

clip_image008

必須

purge table IDENTITY_TEST_TAB,

結論:

  1. Identity Columns 是基於序列實現的
  2. GENERATED IDENTITY 中sequence不能單獨被刪除
  3. GENERATED IDENTITY 中的表刪除,如果存在回收站中,該sequence依然存儲,如果表被徹底刪除,則sequence也被刪除

3.3 執行插入語句時的解釋計划

INSERT INTO identity_test_tab (description) VALUES ('Just DESCRIPTION');

clip_image009

 對比發現:該方式的效率比觸發器+序列的方式高!

四、identity_options

clip_image010

查看表的DDL

select dbms_metadata.get_ddl('TABLE','IDENTITY_TEST_TAB') FROM DUAL;

CREATE TABLE "TEST_USER"."IDENTITY_TEST_TAB"

( "ID" NUMBER GENERATED ALWAYS AS IDENTITY MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE NOT NULL ENABLE,

"DESCRIPTION" VARCHAR2(30)

) SEGMENT CREATION IMMEDIATE

PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255

NOCOMPRESS LOGGING

STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645

PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1

BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)

TABLESPACE "USERS"

INCREMENT BY

用於定義序列的步長,如果省略,則默認為1,如果出現負值,則代表序列的值是按照此步長遞減的。

START WITH

定義Oracle序列的初始值(即產生的第一個值),默認為1。

MAXVALUE

定義序列生成器能產生的最大值。選項NOMAXVALUE是默認選項,代表沒有最大值定義,這時對於遞增序列,系統能夠產生的最大值是10的27次方;對於遞減序列,最大值是-1。

MINVALUE

定義序列生成器能產生的最小值。選項NOMAXVALUE是默認選項,代表沒有最小值定義,

CYCLE和NOCYCLE

表示當序列生成器的值達到限制值后是否循環。CYCLE代表循環,NOCYCLE代表不循環。如果循環,則當遞增序列達到最大值時,循環到最小值;對於遞減序列達到最小值時,循環到最大值。如果不循環,達到限制值后,繼續產生新值就會發生錯誤。

CACHE

(緩沖)定義存放序列的內存塊的大小,默認為20。NOCACHE表示不對序列進行內存緩沖。對序列進行內存緩沖,可以改善序列的性能。

原文地址:

ORACLE 12C 新特性Identity Columns—實現ORACLE自增長列功能

Identity Columns in Oracle Database 12c Release 1 (12.1)

Database SQL Language Reference


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM