ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 主键的变更导致索引无法删除

主键的变更导致索引无法删除

原创 Linux操作系统 作者:yangtingkun 时间:2009-01-06 23:56:12 0 删除 编辑

ITPUB上看到一个有趣的帖子:http://www.itpub.net/thread-1109620-1-1.html。楼主给出了一个例子,由于主键的变更导致用户创建的索引无法被删除。

 

 

下面来重现一下这个问题:

SQL> CREATE TABLE T (ID NUMBER, NAME VARCHAR2(30));

表已创建。

SQL> ALTER TABLE T ADD PRIMARY KEY (ID);

表已更改。

SQL> CREATE INDEX IND_T_ID_NAME ON T (ID, NAME);

索引已创建。

SQL> ALTER TABLE T DISABLE PRIMARY KEY;

表已更改。

SQL> ALTER TABLE T ENABLE PRIMARY KEY;

表已更改。

SQL> DROP INDEX IND_T_ID_NAME;
DROP INDEX IND_T_ID_NAME
           *
1 行出现错误:
ORA-02429:
无法删除用于强制唯一/主键的索引

楼主认为这是一个bug,其实这是一个很正常的现象。下面对上面每个SQL进行说明。

第一个SQL:建表;

第二个SQL:为表T添加了一个主键,不过Oracle为了增加主键,会自动在ID列上创建一个唯一索引;

第三个SQL:手工创建了一个索引,注意这个索引包括了主键列ID

第四个SQLDISABLE主键,OracleDISABLE主键的同时,会自动删除Oracle自动添加的索引。

第五个SQLENABLE主键,OracleENABLE主键的同时,仍然需要一个索引来支持主键,但是由于现在表中已经包含了一个索引IND_T_ID_NAME包含主键列了,所以这次Oracle没有在重新创建一个索引,而是使用了现有的索引作为主键的索引。

第六个SQL:删除索引报错。由于主键存在,没有办法删除主键对应的索引,所以这个错误信息是正常的。

其实楼主的操作可以等价于:

SQL> DROP TABLE T;

表已删除。

SQL> CREATE TABLE T (ID NUMBER, NAME VARCHAR2(30));

表已创建。

SQL> CREATE INDEX IND_T_ID_NAME ON T (ID, NAME);

索引已创建。

SQL> ALTER TABLE T ADD PRIMARY KEY (ID);

表已更改。

SQL> DROP INDEX IND_T_ID_NAME;
DROP INDEX IND_T_ID_NAME
           *
1 行出现错误:
ORA-02429:
无法删除用于强制唯一/主键的索引

首先想要说明的是,并不是所有碰到的错误都是bug,比如这个例子就是一种很正常的情况,只要对Oracle的实现了解比较清楚,就可以很快找到导致问题的原因。再比如前天处理的一个ORA-600错误,其实是SQL的重复数据导致的,并不是真正意义上的bug。这个ORA-600错误的处理可以参考:http://yangtingkun.itpub.net/post/468/476593http://yangtingkun.itpub.net/post/468/476653

另外要说一点,其实一个问题背后总会隐藏着很多的知识,以这个问题为例,想把问题搞清楚,就必须知道:在主键创建时自动创建索引;在DISABLE主键的时候会删除自动创建的索引;在创建主键时,会优先使用现有的索引;当主键存在时,不能删除用于主键的索引等等。

问题还可以再引申一步:OracleDISABLE主键或删除主键时,会删除自动创建的索引,而不会删除用户创建的索引。

最终问题可以引申到,如何判断一个索引是Oracle自动创建的,还是用户手工创建的,关于这个问题可以参考:http://yangtingkun.itpub.net/post/468/160390

 

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

请登录后发表评论 登录
全部评论
暂无介绍

注册时间:2007-12-29

  • 博文量
    1955
  • 访问量
    10469971