需求:
一个表的唯一约束被禁用期间,有脏数据进来,当启用约束时失败。
环境:
-bash-4.1$ uname -a Linux dbtest1 2.6.32-279.el6.x86_64 #1 SMP Wed Jun 13 18:24:36 EDT 2012 x86_64 x86_64 x86_64 GNU/Linux SQL> select * from v$version; BANNER -------------------------------------------------------------------------------- Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production PL/SQL Release 11.2.0.1.0 - Production CORE 11.2.0.1.0 Production TNS for Linux: Version 11.2.0.1.0 - Production NLSRTL Version 11.2.0.1.0 - Production
测试表为scott.test,含有的数据为:
SQL> select * from scott.test; ID VALUE ---------- ---------- 1 2 1 3 1 2 3 2 2
尝试对value列添加唯一约束:
SQL> alter table scott.test add constraint uni_test unique(value); alter table scott.test add constraint uni_test unique(value) * ERROR at line 1: ORA-02299: cannot validate (SCOTT.UNI_TEST) - duplicate keys found
这里发现由于value列存在重复数据,直接添加唯一约束会失败。查看官方文档中,约束有2个参数,可以配置成只对新数据做约束检查,对已存在旧数据约束不生效,如下:
You can specify that a constraint is enabled (ENABLE
) or disabled (DISABLE
). If a constraint is enabled, data is checked as it is entered or updated in the database, and data that does not conform to the constraint is prevented from being entered. If a constraint is disabled, then data that does not conform can be allowed to enter the database.
Additionally, you can specify that existing data in the table must conform to the constraint (VALIDATE
). Conversely, if you specify NOVALIDATE
, you are not ensured that existing data conforms.
An integrity constraint defined on a table can be in one of the following states:
-
ENABLE
,VALIDATE
-
ENABLE
,NOVALIDATE
-
DISABLE
,VALIDATE
-
DISABLE
,NOVALIDATE
来源http://docs.oracle.com/cd/B28359_01/server.111/b28310/general005.htm#ADMIN11538
根据上面的描述,需要使用的为ENABLE,NOVALIDATE这组参数,直接创建该约束会报错,如下:
SQL> alter table scott.test add constraint uni_test unique(value) enable novalidate; alter table scott.test add constraint uni_test unique(value) enable novalidate * ERROR at line 1: ORA-02299: cannot validate (SCOTT.UNI_TEST) - duplicate keys found
需要在该列上先创建一个普通索引,然后再添加约束,如下:
SQL> create index scott.test_idx on scott.test(value); Index created. SQL> alter table scott.test add constraint uni_test unique(value) enable novalidate; Table altered.
检测约束的效果:
SQL> select * from scott.test; ID VALUE ---------- ---------- 1 2 1 3 1 2 3 2 2 SQL> insert into scott.test values (3,3); insert into scott.test values (3,3) * ERROR at line 1: ORA-00001: unique constraint (SCOTT.UNI_TEST) violated SQL> update scott.test set value = 3 where id = 3; update scott.test set value = 3 where id = 3 * ERROR at line 1: ORA-00001: unique constraint (SCOTT.UNI_TEST) violated SQL> insert into scott.test values (4,4); 1 row created.
从上可以看到,该唯一约束添加后,新添加的数据必须符合唯一约束;旧的数据唯一性不做验证,但是唯一列做的update操作是需要做验证的。
注:
1. 除了唯一约束,其它约束也可以设置这两个属性。
2. 删除该约束的时候要先删除对应的索引,然后再删除该约束,否则删除约束操作会失败。