轉發http://www.cnblogs.com/rootq/archive/2008/09/23/1297400.html
disable/enable validate/novalidate 的區別
啟用約束:
enable( validate) :啟用約束,創建索引,對已有及新加入的數據執行約束.
enable novalidate :啟用約束,創建索引,僅對新加入的數據強制執行約束,而不管表中的現有數據.
禁用約束:
disable( novalidate):關閉約束,刪除索引,可以對約束列的數據進行修改等操作.
disable validate :關閉約束,刪除索引,不能對表進行 插入/更新/刪除等操作.
環境:oracle 9i 9.0.1.0 for win,以上結論均測試通過.
例:disable validate約束后,執行update...操作提示:
ORA-25128: 不能對帶有禁用和驗證約束條件 (SYS.PK_EMP_01) 的表進行插入/更新/刪除
=============================================================
今天看到一個關於enable novalidate的問題,以前書上看到過,但沒仔細研究,趁此機會分析了一下,把結果發上來供大家參考.
首先對constraint的開啟和關閉共有四種:enable validate;enable novalidate;disable validate;disable novalidate;
1,3沒有什么好說的,2表示開啟時不檢查已存在數據,4表示不檢查今后的數據.
為此做如下測試:
1.首先創建測試表
create table a (no number(5),name varchar2(10));
insert into a values(1,'ss');
alter table a add constraint pk_a primary key(no);
create table b (no number(5),name varchar2(10));
insert into a values(1,'ss');
ALTER TABLE b ADD CONSTRAINT fk_a_b
FOREIGN KEY (no)
REFERENCES a (no);
2.測試fk
SQL> insert into b values(2,'sd');
insert into b values(2,'sd')
*
ERROR at line 1:
ORA-02291: integrity constraint (SYSTEM.FK_A_B) violated - parent key not found
為此使用
SQL> alter table b disable novalidate constraint fk_a_b;
Table altered.
insert into b values(2,'sdd')
SQL> /
1 row created.
SQL> alter table b enable novalidate constraint fk_a_b;
Table altered.
從上面測試結果可見enable novalidate和disable novalidate在fk等約束是好用的.
3.測試pk
SQL> alter table a disable novalidate primary key;
Table altered.
SQL> insert into a values(1,'sd');
1 row created.
SQL> commit;
Commit complete.
SQL> alter table a enable novalidate primary key;
alter table a enable novalidate primary key
*
ERROR at line 1:
ORA-02437: cannot validate (SYSTEM.SYS_C001578) - primary key violated
在pk測試中enable novalidate不能使用了.
看到kamus的解釋說是enable novalidate主鍵必須是唯一.
查了下相關資料,沒有發現上述說明,但是找到一個下面的說法:
Primary and unique keys must use nonunique indexes
從新做測試
4.測試pk(2)
SQL> alter table a disable novalidate primary key;
Table altered.
這時我去檢查表a,發現主鍵對應的索引pk_a不在了.
手工創建索引
SQL> create index i_a on a(no);
Index created.
SQL> alter table a enable novalidate primary key;
Table altered.
居然成功了.
結論:
從上面的測試結果看出,novalidate在非pk;un時可以正常工作.
在對pk;un使用時需要先創建相關索引,再使用novalidate.
2012.7.10 更新:語法novalidate對添加主鍵約束不起作用 (轉)
最近在看tom的《Effective Oracle by design》,其中第6章6.3.8節有個例子是給表添加主鍵,但是不想對已經存在的數據進行校驗:
alter table dept add constraint dept_pk primary key(deptno) rely enable novalidate;
我經過測試,發現即使加上novalidate語法也還是要檢驗的,測試如下:
SQL> create table aaa as select * from all_users;
Table created
SQL> insert into aaa select * from aaa;
29 rows inserted
SQL> alter table aaa add constraint pk_aaa primary key(username) rely enable novalidate;
alter table aaa add constraint pk_aaa primary key(username) rely enable novalidate
ORA-02437: 無法驗證 (SMS.PK_AAA) - 違反主鍵
該測試在8.1.7.4、9.2.0.6、10.2.0.1中結果都一樣,測試外鍵、check約束也都沒有問題,就是主鍵不行!
最后發現問題所在:
創建主鍵時系統缺省還要同時創建一個唯一索引,novalidate只是使主鍵約束不對已經存在的數據
進行檢驗,並不對創建唯一索引進行控制,所以導致失敗。可以在創建主鍵前先給該字段建個普通
非唯一索引,這樣建主鍵時系統就會自動利用這個普通索引了。
SQL> create index ind_aaa on aaa(username);
Index created
SQL> alter table aaa add constraint pk_aaa primary key(username) rely enable novalidate;
Table altered
測試一下效果:
SQL> insert into aaa (username) values ('SYS');
insert into aaa (username) values ('SYS')
ORA-00001: 違反唯一約束條件 (SMS.PK_AAA)
更新:enable novalidate 和 validate的用處
http://zhaolinjnu.blog.sohu.com/35664664.html
SQL> create table t(id number);
Table created.
SQL> create index idx_t_id on t(id) online;
Index created.
ENABLE VALIDATE specifies that all old and new data also complies with the
constraint. An enabled validated constraint guarantees that all data is and will
continue to be valid.
If any row in the table violates the integrity constraint, the constraint remains
disabled and Oracle returns an error. If all rows comply with the constraint,
Oracle enables the constraint. Subsequently, if new data violates the constraint,
Oracle does not execute the statement and returns an error indicating the
integrity constraint violation.
SQL> select * from t;
ID
----------
1
2
2
SQL> commit;
Commit complete.
SQL> alter table t add constraint pk_t_id primary key(id)
2 enable validate;
alter table t add constraint pk_t_id primary key(id)
*
ERROR at line 1:
ORA-02437: cannot validate (TEST.PK_T_ID) - primary key violated
--enable validate會校驗表中已有的數據是否違背此約束
ENABLE NOVALIDATE ensures that all new DML operations on the constrained
data comply with the constraint. This clause does not ensure that existing data
in the table complies with the constraint and therefore does not require a table
lock.
SQL> alter table t add constraint pk_t_id primary key(id)
2 enable novalidate;
Table altered.
這個過程因為不校驗以前的數據是否違反此約束,只對新數據校驗,所以在業務不繁忙的時候,阻塞DML查詢的時間將會非常短暫。
SQL> insert into t values(1);
insert into t values(1)
*
ERROR at line 1:
ORA-00001: unique constraint (TEST.PK_T_ID) violated
SQL> insert into t values(3);
1 row created.
SQL> commit;
Commit complete.
SQL> select * from t;
ID
----------
1
2
2
3
--enable novalidate參數的含義是不檢查表中已有的數據是否違反約束,但對新插入的數據會檢查
If you specify neither VALIDATE nor NOVALIDATE, the default is VALIDATE.
If you change the state of any single constraint from ENABLE NOVALIDATE to
ENABLE VALIDATE, the operation can be performed in parallel, and does not block
reads, writes, or other DDL operations.
SQL> delete from t where id=2;
2 rows deleted.
SQL> commit;
Commit complete.
SQL> alter table t modify constraint pk_t_id validate;
Table altered.
通過上面的這種將一條創建主鍵的語句變成多條語句
1.create index idx_t_id on t(id) online compute statistics;
2.alter table t add constraint pk_t_id primary key(id)
enable novalidate;
補充:如果是加唯一約束,則用下面的語法:
alter table table_name add constraint uk_table_name unique(column_name...)
enable novalidate;
3.檢查表中重復的主鍵的行
4.alter table t modify constraint pk_t_id validate;
備注:加enable參數的時候,才會阻塞DML語句
這種思路對生產環境有很重要的意義