oracle Deferrable constraint 详解以及用法.
1. 兩種驗證時機.
Oracle的constraints(約束) 根據驗證時機可以分成兩種.
case 1.? 在每一句insert statement 執行時就會馬上驗證, 如果約束驗證失敗,? 則這句sql statement 會執行失敗.
case 2. ? 執行insert statements 時不會驗證,?? 在commit的時候驗證, 如果驗證失敗, 則整個Transaction 回滾.
2.constraints的分類
對應地,? oracle 的 constraints 也可以分成兩大類.
一種是not deferrable (不可以延時的) . 這種情況下只能執行 case1 的驗證時機(即時驗證)
另一種是 defferable (可以設置成延時的).?? 這種情況下可以執行 case 1 或 case2 的驗證時機. 但需要設置.
對于第二種defferable 分類, 還可以分成兩小類.
一種是 initially immediate ,? 意思時默認情況下執行case 1.
另一種是initially deferred,? 意思是默認情況下執行case2.
也就是可以分成三種
1. not deferrable
2. deferrable?? initially immediate
3. deferrable?? initially deferred.
如下圖:
下面會舉一些例子來詳細解釋這個3種 constraints的區別:
2.1 not deferrable constraints
這種最常見也最簡單.? 如果在增加1個constraint 時不指定驗證時機屬性. 默認情況下就會被設為not deferrable.
既然constraint 是不可以延時驗證的,? 所以也不用設定它的初始屬性(實際上就是initially immediate)
例子:
首先我們建立1張空表:
create table T1 (id number(10,0),nm varchar(10));
接下來為id列 增加1個唯一約束t1_id:
SQL> alter table T1 add constraint t1_id unique(id);Table altered.注意這時并沒有指定 Deferrable 屬性, 所以默認情況下就是 not deferrable 的. 我們可以通過user_constraints視圖來檢查它的屬性:
注意Deferrable 屬性是 not deferrable.?? 而 Deferred 屬性(Initially 初始屬性) 是immediate.
這時我們連續執行3句insert sql:
SQL> insert into T1 values(1, 'abc1');1 row created.SQL> insert into T1 values(2, 'abc2');1 row created.SQL> insert into T1 values(2, 'abc3'); insert into T1 values(2, 'abc3') * ERROR at line 1: ORA-00001: unique constraint (BILL.T1_ID) violated可以見到第一第二句insert statement 能正常執行,? 但第三句執行失敗, 因為id=2 與第二句重復了, 約束驗證失敗.?
所以說驗證時機屬于case1, 即時驗證.
這種驗證時機也是最常見的.
2.2 deferrable initially immediate constraints
這種約束默認情況下等于第一種約束(not deferrable), 但是它可以在事務中改變設置, 變成延時驗證的約束.
我們可以這樣理解.??
第一個屬性deferrable 表示 這個約束可以被設置成延時驗證.
第二個屬性initially immediate 表示這個約束默認情況下是即時驗證.
我們繼續利用上面的例子.
首先, 清空上面那個例子表.? 由于上面操作沒有提交, 所以回滾就ok了.
SQL> rollback;Rollback complete.然后我們修改(刪除再建立)那個約束, 射程deferrable initiallly immediate 模式.
SQL> alter table T1 drop constraint t1_id;Table altered.SQL> alter table T1 add constraint t1_id unique(id) initially immediate deferrable ;Table altered.SQL>這時我們去user_constraints視圖檢查屬性:
SQL> select table_name, constraint_name, status, deferrable, deferred, validated from user_constraints where table_name = 'T1';TABLE_NAME CONSTRAINT_NAME STATUS DEFERRABLE DEFERRED VALIDATED ---------- --------------- -------- -------------- --------- ------------- T1 T1_ID ENABLED DEFERRABLE IMMEDIATE VALIDATED可以見到只有1個屬性與Not Defferable constraint有區別,? 就是 deferrable? 屬性是 deferrable了.?? 但是 deferred (初始屬性) 還是 immediate.
我們繼續嘗試插入上面的三行數據:
SQL> insert into T1 values(1, 'abc1');1 row created.SQL> insert into T1 values(2, 'abc2');1 row created.SQL> insert into T1 values(2, 'abc3'); insert into T1 values(2, 'abc3') * ERROR at line 1: ORA-00001: unique constraint (BILL.T1_ID) violated可以到執行結果與上面一模一樣. 沒有區別. 也就是說也是case 1模式.
我們檢索這張表, 只有兩行數據, 然后回滾, 那么就清空這張表了.
SQL> select * from T1;ID NM ---------- ----------1 abc12 abc2SQL> rollback;Rollback complete.SQL> select * from T1;no rows selectedSQL>
好了, 現在就是重點了, deferrable可以在事務中臨時改變成另1種模式.
也就是說可以由case1 臨時設置為 case 2.
syntax:
set constraint? <constraint_name>? deferred/immediate
注意上面的語句并沒有改變這個constraint的任何屬性, 只不過是切換為另一種模式
也就是說初始是immediate模式的,?? 執行上面的語句后就臨時變成deferred模式了.
我們接回上面的例子, 執行另一只模式:
SQL> set constraint t1_id deferred;Constraint set.我們查下這個constraint的屬性, 發現屬性完全無改變,? Deferred屬性還是immediate.? 因為Deferred這個屬性指的是初始屬性.
這時我們insert上面的三條記錄.? 發現3條insert都可以被插入到數據表中.
SQL> insert into T1 values(1, 'abc1');1 row created.SQL> insert into T1 values(2, 'abc2');1 row created.SQL> insert into T1 values(2, 'abc3');1 row created.SQL> select * from T1;ID NM ---------- ----------1 abc12 abc22 abc3SQL>
則說明這時在insert 語句執行時不會執行這個約束的驗證, 三行都被插入到表中了,? 但是在提交時回驗證.
SQL> commit; commit * ERROR at line 1: ORA-02091: transaction rolled back ORA-00001: unique constraint (BILL.T1_ID) violated見到提交失敗, 而且整個事務會回滾,? 也就是說這時表里面連第一第二句的insert記錄也沒有了.
SQL> select * from T1;no rows selected這個跟not defferable constraint有區別啊,? 那種在每一句sql statement執行驗證, 而且驗證失敗時并不會回滾事務.
好了下面也是重點:
當我們commit失敗后被回滾,? 也就是代表當前的事務結束了.?
而上面我們提到過, 使用 set constraint 語句 切換constraint到另一種模式只會在當前事務中生效.
也就是指, 事務結束后, 這個constraint就會返回初始模式!
我們再嘗試插入三條語句:
SQL> insert into T1 values(1, 'abc1');1 row created.SQL> insert into T1 values(2, 'abc2');1 row created.SQL> insert into T1 values(2, 'abc3'); insert into T1 values(2, 'abc3') * ERROR at line 1: ORA-00001: unique constraint (BILL.T1_ID) violated發現再次在第三句執行時被執行即時驗證, 因為在新事務中,? constraint t1_id又切換回 immediate 模式了.
2.3 deferrable initially deferred constraints
如果理解了第二種constraint, 那么最后一種就很簡單了
第一個屬性deferrable 表示 這個約束可以被設置成延時驗證.
第二個屬性initially immediate 表示這個約束默認情況下是延時驗證.
但是可以用set constraint語句 在1個事務中臨時切換為 即時驗證.
總結
以上是生活随笔為你收集整理的oracle Deferrable constraint 详解以及用法.的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Oracle rollup 关键字用法简
- 下一篇: grouping Function