主键约束设置Enable Novalidate时报错

最近项目中要求对一张业务表修改主键,前提是之前的业务数据不能受到影响。我想到了针对约束的enable novalidate, 也就是说 允许已有记录不必满足约束条件,但新增 / 修改的记录必须满足。

我们先回顾一下关于启用和禁用约束的4种组合:
启用约束:
enable( validate):启用约束,创建索引,对已有及新加入的数据执行约束。
enable novalidate 启用约束,创建索引,仅对新加入的数据强制执行约束,而不管表中的现有数据。

禁用约束
disable( novalidate)关闭约束,删除索引,可以对约束列的数据进行修改等操作。
disable validate 关闭约束,删除索引,不能对表进行 插入/更新/删除等操作。

我们针对主键约束的enable novalidate做如下测试。

1.创建测试表

点击( 此处 )折叠或打开
  1. SQL> select * from v$version;

  2. BANNER
  3. ----------------------------------------------------------------
  4. Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi
  5. PL/SQL Release 10.2.0.4.0 - Production
  6. CORE    10.2.0.4.0    Production

  7. TNS for 64-bit Windows: Version 10.2.0.4.0 - Production
  8. NLSRTL Version 10.2.0.4.0 - Production

  9. SQL> create table hoegh(x number,y number,z number,
  10.   2 constraint pk_hoegh primary key(x,y));

  11. Table created

  12. SQL>
  13. SQL> insert into hoegh values(1,1,1);

  14. 1 row inserted

  15. SQL> insert into hoegh values(1,2,1);

  16. 1 row inserted

  17. SQL> commit;

  18. Commit complete

  19. SQL> select * from hoegh;

  20.          X Y Z
  21. ---------- ---------- ----------
  22.          1 1 1
  23.          1 2 1

  24. SQL>

2.删除原有主键

点击( 此处 )折叠或打开
  1. SQL> alter table hoegh drop constraint PK_HOEGH cascade drop index;

  2. Table altered

3.添加新主键并设置Enable Novalidate,报错

点击( 此处 )折叠或打开
  1. SQL> alter table hoegh add constraint PK_HOEGH primary key(x,z) enable novalidate;

  2. alter table hoegh add constraint PK_HOEGH primary key(x,z) enable novalidate

  3. ORA-02437: 无法验证 (HOEGH.PK_HOEGH) - 违反主键

  4. SQL>
我们看到添加主键约束失败了,提示“ORA-02437: 无法验证 (HOEGH.PK_HOEGH) - 违反主键”,也就是说已有的数据不满足新的主键约束; 虽然我们设置了 N ovalidate ,但是和我们预想的结果不一致,数据库仍 然检验了已有数据。
我们知道主键约束=唯一约束+非空约束,那么这个是不是和唯一约束有关系呢?接下来,我们尝试添加一个唯一约束,同时设置Enable Novalidate。

点击(此处)折叠或打开

  1. SQL> alter table hoegh add constraint unq_xz unique(x,z) enable novalidate;

  2. alter table hoegh add constraint unq_xz unique(x,z) enable novalidate

  3. ORA-02299: 无法验证 (HOEGH.UNQ_XZ) - 找到重复关键字

  4. SQL>
我们看到也失败了,看来根源就在这里。创建主键时系统缺省还要同时创建一个唯一索引,novalidate只是使主键约束不对已经存在的数据进行检验,并不对创建唯一索引进行控制,所以导致失败。
那么如何解决这个问题呢?

4.创建普通索引,然后添加主键约束并设置Enable Novalidate,成功

我们可以在创建主键前先给该字段建个普通非唯一索引,这样建主键时系统就会自动利用这个普通索引了。
点击( 此处 )折叠或打开
  1. SQL>
  2. SQL> create index idx_xz on hoegh(x,z);

  3. Index created

  4. SQL> alter table hoegh add constraint PK_HOEGH primary key(x,z) enable novalidate;

  5. Table altered

  6. SQL> insert into hoegh values(1,3,1);

  7. insert into hoegh values(1,3,1)

  8. ORA-00001: 违反唯一约束条件 (HOEGH.PK_HOEGH)

  9. SQL> select * from hoegh;

  10.          X Y Z
  11. ---------- ---------- ----------
  12.          1 1 1
  13.          1 2 1

  14. SQL>
  15. SQL> insert into hoegh values(1,3,2);

  16. 1 row inserted

  17. SQL> commit;

  18. Commit complete

  19. SQL>
  20. SQL> select * from hoegh;

  21.          X Y Z
  22. ---------- ---------- ----------
  23.          1 1 1
  24.          1 2 1
  25.          1 3 2

  26. SQL>
我们看到,已有的记录不受新约束的影响,而新增记录 必须满足新的主键约束。

5.结论

从上面的测试结果看出,enable novalidate在针对主键约束或者唯一约束使用时需要先创建相关索引,再使用 enable novalidate。


                                                                                                                                                                                          ~~~~~~~ the end~~~~~~~~~
                                                                                                                                                                                                               hoegh
                                                                                                                                                                                                           2016.06.19

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/30162081/viewspace-2120425/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/30162081/viewspace-2120425/

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值