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