这两天在开发过程中,有个需求,就是找出某个schema的所有主键索引和唯一约束索引的名称,逻辑中用到了dba_indexes,其中存在一个字段叫UNIQUENESS,官方文档解释是说该字段会标记索引是唯一的(UNIQUE)还是非唯一的(NONUNIQUE),能不能这样理解,对主键索引和唯一约束索引来说,这个字段应该是UNIQUE?
如果按常规创建主键约束,自动创建的索引确实这个字段是UNIQUE,
代码语言:javascript复制SQL> create table t(id number);
Table created.
SQL> alter table t add constraint pk_t primary key(id);
Table altered.
SQL> select table_name, index_name, uniqueness from dba_indexes
2 where table_name='T' and owner='BISAL';
TABLE_NAME INDEX_NAME UNIQUENESS
------------------------- ------------------------- ---------------
T PK_T UNIQUE
如果按常规创建唯一约束,自动创建的索引确实这个字段是UNIQUE,
代码语言:javascript复制SQL> create table t(id number);
Table created.
SQL> alter table t add constraint uk_t unique(id);
Table altered.
SQL> select table_name, index_name, uniqueness from dba_indexes
2 where table_name='T' and owner='BISAL';
TABLE_NAME INDEX_NAME UNIQUENESS
------------------------- ------------------------- ---------------
T UK_T UNIQUE
但如果我们先创建非唯一索引,然后增加主键,主键就会使用这个索引作为主键索引,但是此时索引的UNIQUENESS字段值就是NONUNIQUE,
代码语言:javascript复制SQL> create table t(id number);
Table created.
SQL> create index idx_t on t(id);
Index created.
SQL> alter table t add constraint pk_t primary key(id);
Table altered.
SQL> select table_name, index_name, uniqueness from dba_indexes
2 where table_name='T' and owner='BISAL';
TABLE_NAME INDEX_NAME UNIQUENESS
------------------------- ------------------------- ---------------
T IDX_T NONUNIQUE
但这不会影响主键的功能,
代码语言:javascript复制SQL> insert into t values(1);
1 row created.
SQL> insert into t values(1);
insert into t values(1)
*
ERROR at line 1:
ORA-00001: unique constraint (BISAL.PK_T) violated
同样地,对唯一约束,如果选择先创建非唯一索引,再增加唯一约束的操作,索引字段的UNIQUENESS就是NONUNIQUE,
代码语言:javascript复制SQL> create table t(id number);
Table created.
SQL> alter table t add constraint uk_t unique (id);
Table altered.
SQL> select table_name, index_name, uniqueness from dba_indexes
2 where table_name='T' and owner='BISAL';
TABLE_NAME INDEX_NAME UNIQUENESS
------------------------- ------------------------- ---------------
T IDX_T NONUNIQUE
同样不会影响唯一约束的作用,
代码语言:javascript复制SQL> insert into t valueS(1);
1 row created.
SQL> insert into t values(1);
insert into t values(1)
*
ERROR at line 1:
ORA-00001: unique constraint (BISAL.UK_T) violated
SQL> insert into t values('');
1 row created.
因此,dba_indexes的UNIQUENESS字段值是表示索引的唯一性,和约束没有直接的关联。主键约束和唯一约束所对应的索引UNIQUENESS不一定就是UNIQUE,只有当这两种约束都自动创建索引/手工先创建唯一索引的时候,UNIQUENESS的值才是UNIQUE,但是即使是NONUNIQUE,不会影响主键约束和唯一约束的作用。
碰巧前几天,墨天轮每日一题,出了这道题,和上述操作存在异曲同工之处,
但是这道题不是很严谨,创建成功有前提,就是当前表中不存在重复的数据,如果存在重复的数据,创建会提示错误,如下所示,
代码语言:javascript复制SQL> insert into test values(1);
1 row created.
SQL> insert into test values(1);
1 row created.
SQL> create index idx_test_01 on test(id);
Index created.
SQL> alter table test add constraint pk_test primary key(id);
alter table test add constraint pk_test primary key(id)
*
ERROR at line 1:
ORA-02437: cannot validate (BISAL.PK_TEST) - primary key violated
再扩展下,如果当前表存在重复数据,再创建唯一索引,此时会提示错误,
代码语言:javascript复制SQL> create unique index idx_test_01 on test(id);
create unique index idx_test_01 on test(id)
*
ERROR at line 1:
ORA-01452: cannot CREATE UNIQUE INDEX; duplicate keys found
如果创建了唯一索引,再插入重复的值,会提示唯一约束冲突的错误,但此时其实没有任何约束,
代码语言:javascript复制SQL> create unique index idx_test_01 on test(id);
Index created.
SQL> insert into test values(1);
1 row created.
SQL> insert into test values(1);
insert into test values(1)
*
ERROR at line 1:
ORA-00001: unique constraint (BISAL.IDX_TEST_01) violated
SQL> select constraint_name, index_name from
user_constraints where table_name='TEST';
no rows selected
说明如果仅存在唯一索引的时候,他会保证数据的唯一性。如果存在主键或者唯一约束,即使索引不唯一,还是能限制数据的重复性。