刪除主鍵的時候,索引是否刪除
問題:刪除主鍵時是否會同時自動刪除索引?
答案:是否刪除索引取決於索引是建立主鍵時自動建立的,還是建立主鍵前手工建立的。
如果期望刪除主鍵時,同時刪除索引,安全的做法是增加drop index選項。另外,如果為了防止因存在外來鍵引用而刪除失敗,可以增加cascade選項。
以下內容在PLSQLDeveloper中親測,為了程式碼便於閱讀放到eclipse中做了格式調整。
測試無drop index/keepindex選項時的情況
手工建立索引,後增加主鍵
–建表
SQL> drop table test;
drop table test
ORA-00942: 表或檢視不存在
SQL> create table test(ID INTEGER not null);
Table created
–建主鍵
SQL> create unique index PK_TEST on TEST(ID);
Index created
SQL> alter table TEST
2 add CONSTRAINT PK_TEST PRIMARY KEY (ID) using index;
Table altered
–檢視索引
SQL> select index_name from user_indexes where index_name=’PK_TEST’;
INDEX_NAME
PK_TEST
–刪除主鍵
SQL> alter table TEST drop primary key;
Table altered
–再檢視索引,沒有被刪掉
SQL> select index_name from user_indexes where index_name=’PK_TEST’;
INDEX_NAME
PK_TEST
增加主鍵,自動建立索引
–建表
SQL> drop table test;
Table dropped
SQL> create table test(ID INTEGER not null);
Table created
–新增主鍵,自動建立索引
SQL> alter table TEST
2 add CONSTRAINT PK_TEST PRIMARY KEY (ID) using index;
Table altered
–檢視索引
SQL> select index_name from user_indexes where index_name=’PK_TEST’;
INDEX_NAME
PK_TEST
–刪除主鍵
SQL> alter table TEST drop primary key;
Table altered
–再次檢視索引,已經刪除
SQL> select index_name from user_indexes where index_name=’PK_TEST’;
INDEX_NAME
測試drop index選項時的情況
手工建立索引,後增加主鍵
–建表
SQL> drop table test;
Table dropped
SQL> create table test(ID INTEGER not null);
Table created
–建主鍵
SQL> create unique index PK_TEST on TEST(ID);
Index created
SQL> alter table TEST
2 add CONSTRAINT PK_TEST PRIMARY KEY (ID) using index;
Table altered
–檢視索引
SQL> select index_name from user_indexes where index_name=’PK_TEST’;
INDEX_NAME
PK_TEST
–刪除主鍵
SQL> alter table TEST drop primary key drop index;
Table altered
–再次檢視索引,已經被刪除
SQL> select index_name from user_indexes where index_name=’PK_TEST’;
INDEX_NAME
增加主鍵,自動建立索引
–建表
SQL> drop table test;
Table dropped
SQL> create table test(ID INTEGER not null);
Table created
–建主鍵
SQL> alter table TEST
2 add CONSTRAINT PK_TEST PRIMARY KEY (ID) using index;
Table altered
–檢視索引
SQL> select index_name from user_indexes where index_name=’PK_TEST’;
INDEX_NAME
PK_TEST
–刪除主鍵
SQL> alter table TEST drop primary key drop index;
Table altered
–再次檢視索引,已經被刪除
SQL> select index_name from user_indexes where index_name=’PK_TEST’;
INDEX_NAME
測試keep index選項時的情況
手工建立索引,後增加主鍵
–建表
SQL> drop table test;
Table dropped
SQL> create table test(ID INTEGER not null);
Table created
–建主鍵
SQL> create unique index PK_TEST on TEST(ID);
Index created
SQL> alter table TEST
2 add CONSTRAINT PK_TEST PRIMARY KEY (ID) using index;
Table altered
–檢視索引
SQL> select index_name from user_indexes where index_name=’PK_TEST’;
INDEX_NAME
PK_TEST
SQL> –刪除主鍵
SQL> alter table TEST drop primary key keep index;
Table altered
–再次檢視索引,被保留
SQL> select index_name from user_indexes where index_name=’PK_TEST’;
INDEX_NAME
PK_TEST
增加主鍵,自動建立索引
–建表
SQL> drop table test;
Table dropped
SQL> create table test(ID INTEGER not null);
Table created
–建主鍵
SQL> alter table TEST
2 add CONSTRAINT PK_TEST PRIMARY KEY (ID) using index;
Table altered
–檢視索引
SQL> select index_name from user_indexes where index_name=’PK_TEST’;
INDEX_NAME
PK_TEST
–刪除主鍵
SQL> alter table TEST drop primary key keep index;
Table altered
–再次檢視索引,依然被保留
SQL> select index_name from user_indexes where index_name=’PK_TEST’;
INDEX_NAME
PK_TEST
測試增加drop index選項時使用cascade關鍵字的作用
–新建table1
SQL> create table table1(ID INTEGER not null);
Table created
–新增主鍵約束
SQL> alter table table1 add CONSTRAINT PK_TEST PRIMARY KEY (ID) using index;
Table altered
–插入三個值1,2,3
SQL> insert into table1 values(1);
1 row inserted
SQL> insert into table1 values(2);
1 row inserted
SQL> insert into table1 values(3);
1 row inserted
SQL> select * from table1;
ID
1
2
3
–新建table2
SQL> create table table2(ID1 INTEGER not null,ID2 INTEGER not null);
Table created
–新增table2主鍵約束
SQL> alter table table2 add constraint pk_table2 primary key (ID1) using index;
Table altered
–新增table2外來鍵約束,其id2這一列指向table的id
SQL> alter table table2 add constraint fk_id2 foreign key (ID2) references table1(id);
Table altered
–向table2插入三行值(1,1),(2,2),(3,3)
SQL> insert into table2 values (1,1);
1 row inserted
SQL> insert into table2 values (2,2);
1 row inserted
SQL> insert into table2 values (3,3);
1 row inserted
SQL> select * from table2;
ID1 ID2
1 1
2 2
3 3
–檢視table2的約束,可以看到有主鍵和外來鍵
SQL> select * from user_constraints a where a.table_name=’TABLE2’;
OWNER CONSTRAINT_NAME CONSTRAINT_TYPE TABLE_NAME SEARCH_CONDITION R_OWNER R_CONSTRAINT_NAME DELETE_RULE STATUS DEFERRABLE DEFERRED VALIDATED GENERATED BAD RELY LAST_CHANGE INDEX_OWNER INDEX_NAME INVALID VIEW_RELATED
VOUDATA SYS_C0097617 C TABLE2 “ID1” IS NOT NULL ENABLED NOT DEFERRABLE IMMEDIATE VALIDATED GENERATED NAME 2014/6/10 1
VOUDATA SYS_C0097618 C TABLE2 “ID2” IS NOT NULL ENABLED NOT DEFERRABLE IMMEDIATE VALIDATED GENERATED NAME 2014/6/10 1
VOUDATA PK_TABLE2 P TABLE2 ENABLED NOT DEFERRABLE IMMEDIATE VALIDATED USER NAME 2014/6/10 1 VOUDATA PK_TABLE2
VOUDATA FK_ID2 R TABLE2 VOUDATA PK_TEST NO ACTION ENABLED NOT DEFERRABLE IMMEDIATE VALIDATED USER NAME 2014/6/10 1
–刪除table1主鍵,不使用cascade關鍵字,此時報錯
SQL> alter table table1 drop primary key drop index;
alter table table1 drop primary key drop index
ORA-02273: 此唯一/主鍵已被某些外來鍵引用
–刪除table1主鍵,使用cascade關鍵字,不報錯
SQL> alter table table1 drop primary key cascade drop index;
Table altered
–檢視table2的約束,此時外來鍵已經被幹掉了
SQL> select * from user_constraints a where a.table_name=’TABLE2’;
OWNER CONSTRAINT_NAME CONSTRAINT_TYPE TABLE_NAME SEARCH_CONDITION R_OWNER R_CONSTRAINT_NAME DELETE_RULE STATUS DEFERRABLE DEFERRED VALIDATED GENERATED BAD RELY LAST_CHANGE INDEX_OWNER INDEX_NAME INVALID VIEW_RELATED
VOUDATA SYS_C0097617 C TABLE2 “ID1” IS NOT NULL ENABLED NOT DEFERRABLE IMMEDIATE VALIDATED GENERATED NAME 2014/6/10 1
VOUDATA SYS_C0097618 C TABLE2 “ID2” IS NOT NULL ENABLED NOT DEFERRABLE IMMEDIATE VALIDATED GENERATED NAME 2014/6/10 1
VOUDATA PK_TABLE2 P TABLE2 ENABLED NOT DEFERRABLE IMMEDIATE VALIDATED USER NAME 2014/6/10 1 VOUDATA PK_TABLE2
–檢視table2的資料,沒有變化,說明只是外來鍵關聯去掉了,引用table1的資料保留
SQL> select * from table2;
ID1 ID2
1 1
2 2
3 3
由此可見,若主鍵被其他表引用做外來鍵,刪除主鍵並drop index,若不使用cascade關鍵字則執行會報錯,而使用cascade關鍵字會將其關聯的外來鍵同時刪除。所在這種情況下cascade關鍵字還是謹慎使用,在完全考慮到了外來鍵關聯不需要時再使用,否則可能在未知的情況下將某些外來鍵關聯刪除並且在調整過主鍵後忘記重新增加外來鍵,執行時報錯總好過不知情的情況下少了外來鍵關聯。