Oracle約束constraint的三個屬性應用
Oracle約束constraint是我們經常使用的一種資料庫規則物件。constraint在資料庫中的作用就是從靜態角度對資料完整性進行維護。我們經常使用的主鍵primary key和外來鍵foreign key,本質上就是約束的一種形式。
對Oracle的約束,我們有三個屬性可以進行設定,分別為deferrable、deferred和validated。針對不同的需求設計場景,採用不同型別的屬性,可以幫助我們實現不同的約束效果。下面我們分別來進行實驗。
1、 環境準備
首先我們還是準備資料實驗環境。
SQL> create table t (id number);
Table created
SQL> alter table T
2 add constraint c_t_id1
3 check (id>5);
Table altered
我們建立了資料表T,在列id上新增了約束c_t_id1。約束內容很簡單,就是要求id值保證是大於5。約束c_t_id1使用的是預設選項,資料字典中對該約束的表示如下:
SQL> select constraint_name, constraint_type ctype, SEARCH_CONDITION cond, STATUS, DEFERRABLE, DEFERRED, VALIDATED from dba_constraints where table_name='T' and wner='SYS';
CONSTRAINT_NAME CTYPE COND STATUS DEFERRABLE DEFERRED VALIDATED
-------------------- ----- ---------- -------- -------------- --------- -------------
C_T_ID1 C id>5 ENABLED NOT DEFERRABLE IMMEDIATE VALIDATED
注意,此時約束的三個屬性取值分別為:deferrable: not deferrable;deferred:immediate;validated:validated;
我們觀察一下此時資料表的插入現象:
SQL> insert into t values (1); //插入非法的資料;
insert into t values (1)
ORA-02290: 違反檢查約束條件 (SYS.C_T_ID1) //立刻報錯,將資料剔除!
SQL> insert into t values (6);
1 row inserted
SQL> commit;
Commit complete
SQL> select * from t;
ID
----------
6
結論:在預設情況下,Oracle的約束是不允許延遲(not deferrable)、立即應用和驗證的(immediate、validated)。在資料變化的時候,立即進行約束驗證。
2、 deferrable:約束應用可以延遲
deferrable預設值為not deferrable,字面含義是不可延遲。那麼我們如果設定可以延遲,效果是什麼呢?
SQL> alter table T
2 drop constraint C_T_ID1;
Table altered
SQL> alter table T
2 add constraint C_T_ID1
3 check (id>5)
4 deferrable;
Table altered
此時,資料字典中的情況是如下:
SQL> select constraint_name, SEARCH_CONDITION cond, STATUS, DEFERRABLE, DEFERRED, VALIDATED from dba_constraints where table_name='T' and wner='SYS';
CONSTRAINT_NAME CTYPE STATUS DEFERRABLE DEFERRED VALIDATED
-------------------- ----- -------- -------------- --------- -------------
C_T_ID1 C ENABLED DEFERRABLE IMMEDIATE VALIDATED
與預設情況相比,deferrable屬性變化為了deferrable。我們觀察一下現象:
SQL> insert into t values (3);
insert into t values (3)
ORA-02290: 違反檢查約束條件 (SYS.C_T_ID1)
在插入資料的時候,立即進行約束驗證。和預設情況下沒有差異。那麼怎麼處理呢?
//手工設定deferred屬性為deferred
SQL> set constraint c_t_id1 deferred;
Constraints set
SQL> insert into t values (3); //此時插入資料時候,並不進行驗證操作了。
1 row inserted
SQL> insert into t values (7);
1 row inserted
SQL> commit;
commit
ORA-02091: 事務處理已回退
ORA-02290: 違反檢查約束條件 (SYS.C_T_ID1) //直到進行commit的時候,才會應用約束;
那麼,如何設定回原有的屬性呢?
SQL> set constraint c_t_id1 immediate;
Constraints set
SQL> insert into t values (4); //又恢復插入立刻檢查約束的狀態了?
insert into t values (4)
ORA-02290: 違反檢查約束條件 (SYS.C_T_ID1)
結論:單獨deferrable的含義就是是否允許約束檢查延後進行。單獨設定deferrable為deferrable之後,約束檢查延後是不可以直接使用的,要配合deferred引數,如果該引數是immediate,那麼約束還是在DML的時候進行應用。如果deferred引數設定為deferred,約束就是在事務commit提交的時候應用,出現錯誤就連帶回滾rollback整個事務。
3、 deferred:是否進行延遲應用
從上面的實驗中,我們可以看出deferred屬性是配合deferrable屬性使用的。當deferrable設定為deferrable之後,可以透過set constraints進行deferred屬性的設定,來確定約束應用時點。
本部分確定deferred定義的方式和與deferrable屬性的關係。是可以在定義約束是使用initially關鍵字來確定約束的deferred屬性取值。
SQL> alter table T
2 add constraint C_T_ID1
3 check (id>5)
4 deferrable initially deferred;
Table altered
set constraints語句只有在約束的deferrable屬性設定為deferrable的時候才可以使用。
SQL> alter table T
2 drop constraint C_T_ID1;
Table altered
SQL> alter table T
2 add constraint C_T_ID1
3 check (id>5)
4 ;
Table altered
SQL> set constraint c_t_id1 deferred;
set constraint c_t_id1 deferred
ORA-02447: 無法延遲不可延遲的約束條件
4、 disable禁用約束和validate驗證約束
disable與validate的關係很緊密,相互制約影響。我們觀察下面的實驗:
SQL> alter table t disable constraint c_t_id1;
Table altered
SQL> select constraint_name, SEARCH_CONDITION cond, STATUS, DEFERRABLE, DEFERRED, VALIDATED from dba_constraints where table_name='T' and wner='SYS';
CONSTRAINT_NAME COND STATUS DEFERRABLE DEFERRED VALIDATED
---------------- ---------- -------- -------------- --------- -------------
C_T_ID1 id>5 DISABLED NOT DEFERRABLE IMMEDIATE NOT VALIDATED
透過disable constraint語句,可以對一個約束進行禁用操作。禁用disable下的約束,validated屬性是not validate,也就不起作用的。
SQL> select * from t;
ID
----------
6
2
4
86
資料表約束禁用後,資料完整性被破壞。此時,如果我們直接進行約束啟用。
SQL> alter table t enable constraint c_t_id1;
alter table t enable constraint c_t_id1
ORA-02293: 無法驗證 (SYS.C_T_ID1) - 違反檢查約束條件
SQL> select constraint_name, SEARCH_CONDITION cond, STATUS, DEFERRABLE, DEFERRED, VALIDATED from dba_constraints where table_name='T' and wner='SYS';
CONSTRAINT_NAME COND STATUS DEFERRABLE DEFERRED VALIDATED
---------------- ---------- -------- -------------- --------- -------------
C_T_ID1 id>5 DISABLED NOT DEFERRABLE IMMEDIATE NOT VALIDATED
在約束被啟用的時候,會自動進行檢驗。如果資料不滿足條件,Oracle不會開啟該約束引用。
enable和validate可以配合使用enable novalidate子句使用。
SQL> alter table t enable novalidate constraint c_t_id1;
Table altered
SQL> select constraint_name, SEARCH_CONDITION cond, STATUS, DEFERRABLE, DEFERRED, VALIDATED from dba_constraints where table_name='T' and wner='SYS';
CONSTRAINT_NAME COND STATUS DEFERRABLE DEFERRED VALIDATED
---------------- ---------- -------- -------------- --------- -------------
C_T_ID1 id>5 ENABLED NOT DEFERRABLE IMMEDIATE NOT VALIDATED
此時,只是針對現有T中資料不進行驗證,對新增加變化的資料,同樣會進行驗證。
SQL> insert into t values (45);
1 row inserted
SQL> commit;
Commit complete
SQL> insert into t values (3);
insert into t values (3)
ORA-02290: 違反檢查約束條件 (SYS.C_T_ID1)
5、結論
預設情況下,Oracle constraint是不開啟延遲約束和原有資料保留驗證的。那麼在什麼樣的場景下,我們可以考慮使用這些特性呢?
ü 批次資料匯入、物化檢視重新整理的時候,事務量很大,而且存在資料規律前後顛倒的情況。此時,如果開啟著立即約束應用的開關,可能存在一些暫時性的約束不滿足的情況,從而影響到整個系統的執行。開啟約束延遲驗證,就可以幫助我們解決這個問題;
ü 歷史資料移植。歷史資料存在不規則的情況,很多時候難以滿足我們新系統的資料完整性要求。可以使用not validate的方式,對歷史資料不進行約束控制,而只針對新資料開啟管理;
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/17203031/viewspace-704016/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Oracle資料庫中Constraint約束的四對屬性Oracle資料庫AI
- 10、Oracle中的約 束constraintOracleAI
- oracle 約束(constraint)的幾個引數的小研究OracleAI
- 約束CONSTRAINTAI
- constraint約束AI
- oracle 約束的novalidate 應用Oracle
- Oracle SQL細節總結之constraint約束OracleSQLAI
- MySQL——約束(constraint)詳解MySqlAI
- Oracle約束Constraint對於CBO優化器的作用OracleAI優化
- 【CONSTRAINT】具有唯一性約束的列是否可以插入空值AI
- Oracle約束Oracle
- oracle 約束Oracle
- oracle中的約束Oracle
- oracle impdp的skip_constraint_errors選項跳過唯一約束錯誤OracleAIError
- 建約束(Constraint)時隱式建立索引(Index)及先建立索引後建立約束的區別AI索引Index
- Oracle定義約束 外來鍵約束Oracle
- oracle的延遲約束Oracle
- 雲原生應用的十個關鍵屬性
- REST 的 6 個約束REST
- oracle 約束詳解Oracle
- Oracle約束簡介Oracle
- oracle鍵約束控制Oracle
- 修改oracle的約束欄位Oracle
- MySQL之完整性約束MySql
- 【SQL】15 SQL 約束(Constraints)、NOT NULL 約束、UNIQUE 約束、PRIMARY KEY 約束、FOREIGN KEY 約束、CHECK 約束、DEFAULT約束SQLAINull
- oracle 註釋和約束Oracle
- 新增/刪除約束(Oracle)Oracle
- 專案管理的三重約束專案管理
- 約束Constraint引起CBO執行計劃變化一例AI
- Oracle主鍵約束、唯一鍵約束、唯一索引的區別(轉)Oracle索引
- Oracle資料庫開發——表(資料完整性約束)Oracle資料庫
- oracle外來鍵約束的總結Oracle
- Oracle約束的學習與測試Oracle
- Oracle 11g系列:約束Oracle
- Android應用程式的debug屬性Android
- Oracle如何管理帶約束的B樹索引Oracle索引
- Oracle唯一約束中NULL的處理OracleNull
- Flutter原理:三棵重要的樹(渲染過程、佈局約束、應用檢視的構建等)Flutter