轉自:http://blog.chinaunix.net/uid-20274021-id-1969663.html
我們知道對constraint的開啓和關閉共有四種:enable validate;enable novalidate;disable validate;disable novalidate。
enable validate/disable validate 這兩種沒什麼說的。
enable novalidate/disable novalidate 分別表示開啓時不檢查已存在數據/不檢查今後的數據。
enable novalidate/disable novalidate 分別表示開啓時不檢查已存在數據/不檢查今後的數據。
今天主要對enable novalidate/disable novalidate 做個簡單測試。
SQL> create table pk1(id number(2),name varchar2(8));
表已創建。
SQL> insert into pk1 values(1,'abc');
已創建 1 行。
SQL> alter table pk1 add constraint pk_pk1 primary key(id); --設置主鍵約束。
表已更改。
SQL> create table fr1(id number(2),name varchar2(8));
表已創建。
SQL> insert into fr1 values(1,'abc');
已創建 1 行。
SQL> alter table fr1 add constraint fk_fr1 foreign key(id) references pk1(id);
表已更改。
--設置外鍵。
測試外鍵下使用enable novalidate/disable novalidate的情況
SQL> insert into fr1 values(2,'aaa');
insert into fr1 values(2,'aaa')
*
第 1 行出現錯誤:
ORA-02291: 違反完整約束條件 (SYS.FK_FR1) - 未找到父項關鍵字
insert into fr1 values(2,'aaa')
*
第 1 行出現錯誤:
ORA-02291: 違反完整約束條件 (SYS.FK_FR1) - 未找到父項關鍵字
SQL> alter table fr1 disable novalidate constraint fk_fr1;
表已更改。
SQL> insert into fr1 values(2,'aaa');
已創建 1 行。
SQL> select * from fr1;
ID NAME
---------- --------
1 abc
2 aaa
---------- --------
1 abc
2 aaa
SQL> alter table fr1 enable validate constraint fk_fr1;
alter table fr1 enable validate constraint fk_fr1
*
第 1 行出現錯誤:
ORA-02298: 無法驗證 (SYS.FK_FR1) - 未找到父項關鍵字
alter table fr1 enable validate constraint fk_fr1
*
第 1 行出現錯誤:
ORA-02298: 無法驗證 (SYS.FK_FR1) - 未找到父項關鍵字
SQL> alter table fr1 enable novalidate constraint fk_fr1;
表已更改。
--從上面測試結果可見enable novalidate和disable novalidate在外鍵約束下使用是好用的。
測試主鍵下使用enable novalidate/disable novalidate的情況
SQL> select * from pk1;
ID NAME
---------- --------
1 abc
---------- --------
1 abc
SQL> alter table pk1 disable novalidate primary key;
alter table pk1 disable novalidate primary key
*
第 1 行出現錯誤:
ORA-02297: 無法禁用約束條件 (SYS.PK_PK1) - 存在相關性
alter table pk1 disable novalidate primary key
*
第 1 行出現錯誤:
ORA-02297: 無法禁用約束條件 (SYS.PK_PK1) - 存在相關性
SQL> alter table fr1 disable validate constraint fk_fr1;
表已更改。
SQL> alter table pk1 disable novalidate primary key;
表已更改。
SQL> insert into pk1 values(1,'ccc');
已創建 1 行。
SQL> select * from pk1;
ID NAME
---------- --------
1 abc
1 ccc
---------- --------
1 abc
1 ccc
SQL> alter table pk1 enable novalidate primary key;
alter table pk1 enable novalidate primary key
*
第 1 行出現錯誤:
ORA-02437: 無法驗證 (SYS.PK_PK1) - 違反主鍵
alter table pk1 enable novalidate primary key
*
第 1 行出現錯誤:
ORA-02437: 無法驗證 (SYS.PK_PK1) - 違反主鍵
SQL> select INDEX_NAME,TABLE_NAME,TABLE_OWNER from user_indexes where index_name
='PK_PK1';
='PK_PK1';
未選定行
--主鍵對應的索引PK_PK1已經不在了。
SQL> create index cc on pk1(id);
索引已創建。
SQL> alter table pk1 enable novalidate primary key;
表已更改。
--OK了。
--從上面的測試結果看出:novalidate在非主鍵,唯一鍵時可以正常工作。在對主鍵,唯一鍵使用時需要先創建相關索引,再使用novalidate。Primary and unique keys must use nonunique indexes。
舉一個使用novalidate的案例:
給一個有數據的表增加一個非空的列。要求:需要在該表上增加一個字段status,但該字段不能爲空,歷史數據可以爲空。最後將歷史數據的該新加字段統一置爲1
SQL> desc pk1;
名稱 是否爲空? 類型
----------------------------------------- -------- -------------
名稱 是否爲空? 類型
----------------------------------------- -------- -------------
ID NOT NULL NUMBER(2)
NAME VARCHAR2(8)
NAME VARCHAR2(8)
SQL> select * from pk1;
ID NAME
---------- --------
1 abc
2 cba
---------- --------
1 abc
2 cba
SQL> alter table pk1 add status number(1);
表已更改。
SQL> alter table pk1 modify status not null enable novalidate;
表已更改。
SQL> select * from pk1;
ID NAME STATUS
---------- -------- ----------
1 abc
2 cba
---------- -------- ----------
1 abc
2 cba
SQL> update pk1 set status=1;
已更新2行。
SQL> commit;
提交完成。
SQL> select * from pk1;
ID NAME STATUS
---------- -------- ----------
1 abc 1
2 cba 1
---------- -------- ----------
1 abc 1
2 cba 1
SQL> insert into pk1 values(3,'bca',null);
insert into pk1 values(3,'bca',null)
*
第 1 行出現錯誤:
ORA-01400: 無法將 NULL 插入 ("SYS"."PK1"."STATUS")