技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> Oracle --> 怪异ORA-01502,创建唯一约束却无唯一索引

怪异ORA-01502,创建唯一约束却无唯一索引

浏览:1366次  出处信息

    我们都知道,唯一约束是基于唯一索引的,如果没有唯一索引,那么在建立唯一约束的时候会自动创建相应的唯一索引。而今天我在创建唯一约束以后,发生了一件怪异的事情。

    下面是过程描述。
因业务要求,要求在一表(test)上一列增加一个唯一约束,由于是在开发环境,数据量也很小,我采用了如下的方法来创建:
SQL> alter table test
  2    add constraint UK_ET_AIRSUP_USERS_supp_WW unique (air_supply_wangwang)
  3    using index
  4    tablespace TBS_ET_IND
  5    online
  6    compute statistics;

    Table altered.

    理论上按照这种方式,已经完全完成工作了。可是,后来测试人员测试的是,却告诉我发生了如下错误:
ORA-01502: index \'.\' or partition of such index is in unusable state

    查询错误描述,可以很清楚的发现问题的原因:
[oracle@crmtest worksh]$ oerr ora 01502
01502, 00000, "index \'%s.%s\' or partition of such index is in unusable state"
// MERGE: 1489 RENUMBERED TO 1502
// *Cause: An attempt has been made to access an index or index partition
//         that has been marked unusable by a direct load or by a DDL
//         operation
// *Action: DROP the specified index, or REBUILD the specified index, or
//         REBUILD the unusable index partition

    昨天都是没有问题,因此我就怀疑我今天这个唯一约束出了问题,查询了一下表的index:
SQL> select index_name,index_type,status from user_indexes where table_name = upper(\'test\');

    INDEX_NAME                     INDEX_TYPE                  STATUS
------------------------------ --------------------------- --------
PK_ET_AIRSUPPLY_USERS          NORMAL                      VALID
UK_ET_AIRSUPPLY_USERS_NICK     NORMAL                      VALID

    怪异的时候发生了,怎么没有相应的唯一索引呢?确定看看唯一约束有没有什么问题:
SQL> alter table test
  2  modify constraint UK_ET_AIRSUP_USERS_SUPP_WW enable validate;

    Table altered.

    再看看结果如何:
SQL> select index_name,index_type,status from user_indexes where table_name = upper(\'test\');

    INDEX_NAME                     INDEX_TYPE                  STATUS
------------------------------ --------------------------- --------
PK_ET_AIRSUPPLY_USERS          NORMAL                      VALID
UK_ET_AIRSUPPLY_USERS_NICK     NORMAL                      VALID

    SQL> delete from test t where t.id in (\'1\',\'2\',\'3\')
  2  ;
delete from test t where t.id in (\'1\',\'2\',\'3\')
*
ERROR at line 1:
ORA-01502: index \'.\' or partition of such index is in unusable state

    还是不对。于是决定重建这个唯一约束:
SQL> select index_name,index_type,status from user_indexes where table_name = upper(\'test\');

    INDEX_NAME                     INDEX_TYPE                  STATUS
------------------------------ --------------------------- --------
PK_ET_AIRSUPPLY_USERS          NORMAL                      VALID
UK_ET_AIRSUPPLY_USERS_NICK     NORMAL                      VALID

    SQL> alter table test
  2  drop constraint UK_ET_AIRSUP_USERS_SUPP_WW;

    Table altered.

    SQL> select index_name,index_type,status from user_indexes where table_name = upper(\'test\');

    INDEX_NAME                     INDEX_TYPE                  STATUS
------------------------------ --------------------------- --------
PK_ET_AIRSUPPLY_USERS          NORMAL                      VALID
UK_ET_AIRSUPPLY_USERS_NICK     NORMAL                      VALID

    SQL> delete from test t where t.id in (\'1\',\'2\',\'3\');

    0 rows deleted.

    SQL> alter table test
  2    add constraint UK_ET_AIRSUP_USERS_supp_WW unique (air_supply_wangwang)
  3    using index
  4    tablespace TBS_ET_IND
  5    online
  6    compute statistics;

    Table altered.

    SQL> delete from test t where t.id in (\'1\',\'2\',\'3\');

    0 rows deleted.

    SQL> rollback;

    Rollback complete.

    SQL> select index_name,index_type,status from user_indexes where table_name = upper(\'test\');

    INDEX_NAME                     INDEX_TYPE                  STATUS
------------------------------ --------------------------- --------
PK_ET_AIRSUPPLY_USERS          NORMAL                      VALID
UK_ET_AIRSUPPLY_USERS_NICK     NORMAL                      VALID
UK_ET_AIRSUP_USERS_SUPP_WW     NORMAL                      VALID

    
SQL> select * from v$version;

    BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.6.0 - Production
PL/SQL Release 9.2.0.6.0 - Production
CORE    9.2.0.6.0       Production
TNS for Linux: Version 9.2.0.6.0 - Production
NLSRTL Version 9.2.0.6.0 - Production
这个时候问题已经解决。但是这个事件有点诡异,这个错误也无法重现,只是想提醒一下,可能会出现这种现象,虽然它几率很小。

    为了避免此类错误的出现,最好的解决方法,至少在生产库上做操作,可以先自己手工创建唯一索引,然后在创建约束,这样就万无一失了。

QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1