天天看點

我的Oracle 9i學習日志(18)-- 維護資料完整性.b

<b>建立禁止性限制:</b>

•加disable關鍵字即可。

SQL&gt; create table t(id int, name char(10));

表已建立。

SQL&gt; desc t

 名稱                                      是否為空? 類型

 ----------------------------------------- -------- -------------------------

 ID                                                 NUMBER(38)

 NAME                                               CHAR(10)

SQL&gt; alter table t add constraint uq_t_id unique(id) disable;

表已更改。

SQL&gt; insert into t values(0,'aaa');

已建立 1 行。

SQL&gt;

SQL&gt; select * from t;

        ID NAME

---------- --------------------------------------------------

         0 aaa

<b>啟用限制:</b>

SQL&gt; delete from t;

已删除4行。

SQL&gt; alter table t enable unique;

alter table t enable unique

                          *

ERROR 位于第 1 行:

ORA-00906: missing left parenthesis

SQL&gt; alter table t enable unique(id);

insert into t values(0,'aaa')

*

ORA-00001: unique constraint (LUO.UQ_T_ID) violated

SQL&gt; select object_name,object_type from user_objects;

OBJECT_NAME                    OBJECT_TYPE

------------------------------ ------------------------------------

BONUS                          TABLE

CUSTOMERS                      TABLE

DINGDAN                        TABLE

ORDERS                         TABLE

PK_CUST                        INDEX

T                              TABLE

UQ_EMP_ID                      INDEX

UQ_T_ID                        INDEX

已選擇8行。

SQL&gt; drop table t;

表已丢棄。

SQL&gt; alter table t add constraint pk_t_id primary key(id) disable;

已選擇7行。

SQL&gt; insert into t values(1,'aaa');

SQL&gt; insert into t values(1,'bbb');

SQL&gt; commit;

送出完成。

         1 aaa

         1 bbb

SQL&gt; delete from t where name='bbb';

已删除 1 行。

SQL&gt; commit ;

SQL&gt; alter table t enable primary key;                           #啟用主鍵限制可以不用帶列名。

insert into t values(1,'bbb')

ORA-00001: unique constraint (LUO.PK_T_ID) violated

SQL&gt; insert into t values(2,'bbb');

         2 bbb

ORDERS                         TABLE

PK_T_ID                        INDEX

SQL&gt; alter table t disable primary key;                          #再次禁用。

BONUS                          TABLE

已選擇7行。                                    #索引消失。

<b>删除限制:</b>

Alter table bonus drop constraint ck_bonus;

删除unique或主鍵限制時,如果是被引用為外鍵的則帶上cascade參數,删除unique限制同時删除了子表的外鍵限制。

Alter table bonus drop primary key cascade;

實驗:

SQL&gt; select constraint_name,status,validated from user_constraints;

CONSTRAINT_NAME                STATUS           VALIDATED

------------------------------ ---------------- --------------------------

SYS_C002763                    ENABLED          VALIDATED

CK_BONUS                       ENABLED          VALIDATED

CK_BONUS2                      ENABLED          VALIDATED

UQ_EMP_ID                      ENABLED          VALIDATED

PK_CUST                        ENABLED          VALIDATED

FK_CUST                        ENABLED          VALIDATED

CK_DPTID                       ENABLED          VALIDATED

SQL&gt; alter table bonus drop constraint ck_bonus2;

CONSTRAINT_NAME                STATUS           VALIDATED

FK_CUST                        ENABLED          VALIDATED

已選擇6行。

SQL&gt; alter table customers drop primary key cascade;

<b>限制狀态:</b>

<a target="_blank" href="http://blog.51cto.com/attachment/201004/105557890.png"></a>

圖5

可以啟用(ENABLE) 或禁用(DISABLE) 完整性限制。如果啟用某個限制,則在資料庫中輸入或更新資料時,就會對資料進行檢查。禁止輸入不符合限制規則的資料。如果禁用某個限制,則可以在資料庫中輸入不符合限制規則的資料。完整性限制可處于以下狀态之一:

• DISABLE NOVALIDATE

• DISABLE VALIDATE

• ENABLE NOVALIDATE

• ENABLE VALIDATE

DISABLE NOVALIDATE:不檢查處于DISABLE NOVALIDATE 狀态的限制。表中的資料(包括輸入或更新的新資料)可以不符合限制所定義的規則。

DISABLE VALIDATE:當限制處于此狀态時,不允許對受限制的列進行任何修改。另外,限制上的索引将被删除并且禁用限制。注:如果限制可延遲,則不删除索引。

ENABLE NOVALIDATE:如果限制處于此狀态,則不能輸入違反限制的新資料。但是,表可能包含無效的資料,即資料違反限制。啟用處于NOVALIDATE 狀态的限制對正在上載有效OLTP 資料的資料倉庫配置是非常有用的。

ENABLE VALIDATE:如果限制處于此狀态,則不能将違反限制的行插入到表中。但是,禁用該限制時,可以插入此類行。此類行稱為該限制的例外。如果限制處于ENABLE NOVALIDATE 狀态,則在禁用限制時輸入的資料所引起的違反情況仍然存在。要将限制置于已驗證狀态,必須更新或删除違反限制的行。

當某一限制由禁用狀态更改為ENABLE VALIDATE 時,将鎖定表并對表中的所有資料進行一緻性檢查。這可能會引起DML 操作(如等待資料加載),是以,建議先從禁用狀态轉為ENABLE NOVALIDATE,然後再轉為ENABLE VALIDATE。

這些狀态之間的轉換須符合以下規則:

• 除非指定NOVALIDATE,否則ENABLE 表示VALIDATE。

• 除非指定VALIDATE,否則DISABLE 表示NOVALIDATE。

• VALIDATE 和NOVALIDATE 沒有預設的ENABLE 和DISABLE 狀态。

• 當唯一鍵或主鍵從DISABLE 狀态轉為ENABLE 狀态且沒有現有索引時,将自動建立唯一索引。(如果索引可延遲,則将存在異常。)與此類似,當唯一鍵或主鍵從ENABLE 轉為DISABLE 且是使用唯一索引啟用時,則删除該唯一索引。

• 當任何限制從NOVALIDATE 狀态轉為VALIDATE 狀态時,必須檢查所有的資料。但是,從VALIDATE 轉為NOVALIDATE 時,将忽略資料已經過檢查這一事實。

• 将單個限制從ENABLE NOVALIDATE 狀态轉為ENABLE VALIDATE 狀态時,并不禁止使用讀取、寫入或其它DDL 語句。

SQL&gt; select constraint_name,table_name,status,validated from user_constraints;

CONSTRAINT_NAME TABLE_NAME           STATUS           VALIDATED

--------------- -------------------- ---------------- -------------------------

CK_BONUS        BONUS                ENABLED          VALIDATED

UQ_EMP_ID       BONUS                ENABLED          VALIDATED

 ----------------------------------------- -------- ---------------------------

 DPT_ID                                             NUMBER(38)

SQL&gt; alter table t add constraint ck_dptid check(dpt_id&gt;=10) disable;

SQL&gt; insert into t values(1,'aaa ',1);

SQL&gt; insert into t values(2,'bbb',2);

SQL&gt; insert into t values(3,'ccc',3);

        ID NAME                                                   DPT_ID

---------- -------------------------------------------------- ----------

         1 aaa                                                         1

         2 bbb                                                         2

         3 ccc                                                         3

SQL&gt; alter table t enable novalidate constraint ck_dptid;

CK_BONUS        BONUS                ENABLED          VALIDATED

CK_DPTID        T                    ENABLED          NOT VALIDATED

SQL&gt; insert into t values(3,'ddd',4);

insert into t values(3,'ddd',4)

ORA-02290: check constraint (LUO.CK_DPTID) violated

SQL&gt; insert into t values(3,'ddd',11);

#啟用enable novalidate狀态成功。

SQL&gt; select constraint_name,table_name,status,validated from user_constrai

--------------- -------------------- ---------------- --------------------

UQ_EMP_ID       BONUS                ENABLED          VALIDATED

PK_T_ID         T                    DISABLED         NOT VALIDATED

         1 aaa                                                         1

         3 ccc                                                         3

         3 ddd                                                        11

SQL&gt; alter table t enable novalidate primary key;

alter table t enable novalidate primary key

ORA-02437: cannot validate (LUO.PK_T_ID) - primary key violated

#報錯的原因是因為啟用主鍵限制後會建立一個非唯一性索引,但表中有重複值,索引建立不成功。解決方法可以删除表中主鍵列的重複值,或用下面的方法。

SQL&gt; create index t_id on t(id);

索引已建立。

T_ID                           INDEX

UQ_EMP_ID                     INDEX

SQL&gt; insert into t values(2,'eee',12);

insert into t values(2,'eee',12)

SQL&gt; insert into t values(4,'eee',12);

當有大量資料處理時,一緻性限制同索引一樣會降低資料庫性能。是以,可以按以下方法提高性能。

<a target="_blank" href="http://blog.51cto.com/attachment/201004/105627792.png"></a>

圖6

<b>限制檢查時間:</b>

<a target="_blank" href="http://blog.51cto.com/attachment/201004/105647491.png"></a>

圖7

在限制定義完成以後,nondeferred與deferred不能互相轉變。

SET CONSTRAINTS 語句用于将特定事務處理的限制設定為DEFERRED 或IMMEDIATE。

可以使用此語句設定限制名稱清單或限制的模式。SET CONSTRAINTS 模式将一直持續到事務處理完成或者另一個SET CONSTRAINTS 語句重置模式。SET CONSTRAINTS 語句不允許在觸發器内部使用。

ALTER SESSION 語句還包含将限制設定為IMMEDIATE 或DEFERRED 的子句SET CONSTRAINTS。此指令預設為設定所有(ALL) 可延遲的限制(不能指定限制名稱清單)。

ALTER SESSION SET CONSTRAINTS 語句僅适用于目前的會話。

ALTER SESSION

SET CONSTRAINT[S] =

{IMMEDIATE|DEFERRED|DEFAULT}

SET CONSTRAINT | CONSTRAINTS

{constraint |ALL }

{IMMEDIATE|DEFERRED}

SQL&gt; create table t(id int,name char(10),dpt_id int);

SQL&gt; desc t;

 ----------------------------------------- -------- ----------------------

SQL&gt; alter table t add constraint pk_t_id primary key(id);

SQL&gt; select index_name,uniqueness from user_indexes;

INDEX_NAME                                                   UNIQUENESS

------------------------------------------------------------ -------------

PK_T_ID                                                      UNIQUE

SQL&gt; alter table t drop primary key;

SQL&gt; alter table t add constraint pk_t_id primary key(id) deferrable;

PK_T_ID                                                      NONUNIQUE

SQL&gt; alter table t disable primary key;

#如果索引是非唯一性索引,在disable主鍵限制時,不會删除相應索引。

SQL&gt; insert into t values(1,'aaa',1);

PK_T_ID         T                    ENABLED          NOT VALIDATED

insert into t values(1,'aaa',1)

SQL&gt; set constraints all deferred;

限制條件已設定。

         1 aaa                                                         1

         1 aaa                                                         1

commit

ORA-02091: transaction rolled back

本文轉自 d185740815 51CTO部落格,原文連結:http://blog.51cto.com/luotaoyang/293804,如需轉載請自行聯系原作者