经常有开发人员找DBA,需要把唯一索引改为普通索引,或者把主键改为唯一索引或普通索引...
主键属性:普通索引+唯一约束+not null约束 或者唯一索引+not null约束
唯一索引属性:普通索引+唯一约束
最佳实践:
主键用唯一索引+主键约束两步骤来创建,可直接变更为唯一索引
唯一索引用普通索引+唯一约束两步骤来创建,可以直接变更为普通索引
主键不同创建方式,不同的ddl变更结果:测试表如下
create table TEST01 ( col_date date, col2_str VARCHAR2(100), col3_str VARCHAR2(40), col4_str VARCHAR2(40), col5_str VARCHAR2(40) );
1)、直接添加主键约束
alter table TEST01 add constraint PK_TEST01 primary key (COL_DATE); --查看该表上索引情况 set linesize 400 col owner for a10 col index_name for a20 col index_type for a10 col table_owner for a10 col table_name for a20 col uniqueness for a10 col constraint_name for a20 col constraint_type for a10 col index_owner for a10 col STATUS for a10 select owner,index_name,index_type,table_owner,table_name,uniqueness from DBA_INDEXES where table_name='TEST01'; OWNER INDEX_NAME INDEX_TYPE TABLE_OWNE TABLE_NAME UNIQUENESS ---------- -------------------- ---------- ---------- -------------------- ---------- SCOTT PK_TEST01 NORMAL SCOTT TEST01 UNIQUE --查看下该表上约束情况 OWNER CONSTRAINT_NAME CONSTRAINT TABLE_NAME INDEX_OWNE INDEX_NAME STATUS ---------- -------------------- ---------- -------------------- ---------- -------------------- ---------- SCOTT PK_TEST01 P TEST01 SCOTT PK_TEST01 ENABLED 可以看到直接添加主键约束后,Oracle会自动帮你创建一个和约束名相同的唯一索引,并且添加了主键约束。
能否把主键直接变更为唯一索引?
alter table test01 disable constraint PK_TEST01; --检查索引和约束情况 select owner,index_name,index_type,table_owner,table_name,uniqueness from DBA_INDEXES where table_name='TEST01'; no rows selected select t.owner,t.constraint_name,t.constraint_type,t.table_name,t.index_owner,t.index_name,STATUS from dba_constraints t where t.table_name='TEST01'; OWNER CONSTRAINT_NAME CONSTRAINT TABLE_NAME INDEX_OWNE INDEX_NAME STATUS ---------- -------------------- ---------- -------------------- ---------- -------------------- ---------- SCOTT PK_TEST01 P TEST01 DISABLED 可以看到没有索引了
结论:不能直接变更,禁用/删除主键约束后,会发现系统自动创建的唯一索引消失。
2)、创建唯一索引+主键约束
alter table test01 drop constraint PK_TEST01; create unique index scott.uidx_col_date on scott.test01(col_date); alter table TEST01 add constraint PK_TEST01 primary key (COL_DATE); --检查索引和约束情况 select owner,index_name,index_type,table_owner,table_name,uniqueness from DBA_INDEXES where table_name='TEST01'; OWNER INDEX_NAME INDEX_TYPE TABLE_OWNE TABLE_NAME UNIQUENESS ---------- -------------------- ---------- ---------- -------------------- ---------- SCOTT UIDX_COL_DATE NORMAL SCOTT TEST01 UNIQUE select t.owner,t.constraint_name,t.constraint_type,t.table_name,t.index_owner,t.index_name,STATUS from dba_constraints t where t.table_name='TEST01'; OWNER CONSTRAINT_NAME CONSTRAINT TABLE_NAME INDEX_OWNE INDEX_NAME STATUS ---------- -------------------- ---------- -------------------- ---------- -------------------- ---------- SCOTT PK_TEST01 P TEST01 SCOTT UIDX_COL_DATE ENABLED 可以看到主键约束中使用到了创建的唯一索引
能否把主键直接变更为唯一索引?
alter table test01 disable constraint PK_TEST01; --检查索引和约束情况 select owner,index_name,index_type,table_owner,table_name,uniqueness from DBA_INDEXES where table_name='TEST01'; OWNER INDEX_NAME INDEX_TYPE TABLE_OWNE TABLE_NAME UNIQUENESS ---------- -------------------- ---------- ---------- -------------------- ---------- SCOTT UIDX_COL_DATE NORMAL SCOTT TEST01 UNIQUE select t.owner,t.constraint_name,t.constraint_type,t.table_name,t.index_owner,t.index_name,STATUS from dba_constraints t where t.table_name='TEST01'; OWNER CONSTRAINT_NAME CONSTRAINT TABLE_NAME INDEX_OWNE INDEX_NAME STATUS ---------- -------------------- ---------- -------------------- ---------- -------------------- ---------- SCOTT PK_TEST01 P TEST01 DISABLED 可以看到创建的唯一索引还在的
结论:可以直接变更,禁用/删除主键约束后,会发现分开创建的唯一索引还在。
和主键创建方式类似,唯一索引也可以用普通索引+唯一约束来创建,好处是可以禁用/删除唯一约束,直接变更为普通索引
create index scott.idx_col_date on scott.test01(col_date); alter table TEST01 add constraint UK_TEST01 unique (COL_DATE); --检查索引和约束情况 select owner,index_name,index_type,table_owner,table_name,uniqueness from DBA_INDEXES where table_name='TEST01'; OWNER INDEX_NAME INDEX_TYPE TABLE_OWNE TABLE_NAME UNIQUENESS ---------- -------------------- ---------- ---------- -------------------- ---------- SCOTT IDX_COL_DATE NORMAL SCOTT TEST01 NONUNIQUE select t.owner,t.constraint_name,t.constraint_type,t.table_name,t.index_owner,t.index_name,STATUS from dba_constraints t where t.table_name='TEST01'; OWNER CONSTRAINT_NAME CONSTRAINT TABLE_NAME INDEX_OWNE INDEX_NAME STATUS ---------- -------------------- ---------- -------------------- ---------- -------------------- ---------- SCOTT UK_TEST01 U TEST01 SCOTT IDX_COL_DATE ENABLED