【INDEX】Oracle中主键、唯一约束与唯一索引之区别

一、             概述

一般在 Oracle 数据表中,我们都会看到主键,索引,也会看到唯一索引、唯一约束,那么他们有什么区别呢,下面通过一个小实验简单了解一下。

二、             实验过程:
首先创建一个表,并完成主键、唯一约束、唯一索引的创建,如下所示:

SQL>-- 数据库版本
SQL> select * from v$version;

BANNER

----------------------------------------------------------------

Oracle  Database 10g Enterprise Edition Release 10.2.0.5.0 - 64bi

PL/SQL  Release 10.2.0.5.0 - Production

CORE    10.2.0.5.0      Production

TNS  for Linux: Version 10.2.0.5.0 - Production

NLSRTL  Version 10.2.0.5.0 – Production

SQL> conn firsoul/firsoul

Connected.

SQL> -- 创建测试表

SQL> create table test (tno number(5),tname  varchar2(20),tid int);

Table created.

SQL>-- 添加主键

SQL> alter table test add constraint pk_test_tno  primary key(tno);

Table altered.

SQL>-- 添加唯一约束

SQL> alter table test add constraint  uk_test_tname unique(tname);

Table altered.

SQL>-- 添加唯一索引

SQL> create unique index idx_test_tid on  test(tid);

Index created.


向表 TEST 中插入数据,测试

SQL> insert into test values(1,'firsoul',123);

1 row created.

SQL> 1

  1* insert  into test values(1,'firsoul',123)

SQL> /

insert into test values(1,'firsoul',123)

*

ERROR at line 1:

ORA-00001: unique constraint (FIRSOUL.PK_TEST_TNO)  violated

SQL> insert into test values(2,'firsoul',123456);

insert into test values(2,'firsoul',123456)

*

ERROR at line 1:

ORA-00001: unique constraint (FIRSOUL.UK_TEST_TNAME)  violated

SQL> insert into test values(2,'ljx',123);

insert into test values(2,'ljx',123)

*

ERROR at line 1:

ORA-00001: unique constraint (FIRSOUL.IDX_TEST_TID)  violated
SQL> insert into test values(null,'ljx',124);

insert into test values(null,'ljx',124)

                        *

ERROR at line 1:

ORA-01400: cannot insert NULL into  ("FIRSOUL"."TEST"."TNO")

SQL> insert into test values(2,null,null);

1 row created.

SQL> commit;

Commit complete.

  有以上信息,我们可以看出主键列的值不允许为 NULL ,也不允许出现重复值,唯一约束、唯一索引列的值允许为 NULL ,但不允许出现重复值。
 
查看字典表中约束的情况

SQL> set lines 150

SQL> col table_name for a15

SQL> col column_name for a15

SQL> col constraint_name for a20

SQL> select  table_name,column_name,constraint_name from user_cons_columns where table_name=upper('test');

TABLE_NAME       COLUMN_NAME     CONSTRAINT_NAME

--------------- --------------- --------------------

TEST             TNO             PK_TEST_TNO

TEST             TNAME           UK_TEST_TNAME


查看字典表中索引的情况

SQL> select table_name,column_name,index_name  from user_ind_columns where table_name=upper('test');

TABLE_NAME       COLUMN_NAME     INDEX_NAME

--------------- ---------------  ------------------------------

TEST             TNO             PK_TEST_TNO

TEST             TNAME           UK_TEST_TNAME

TEST             TID             IDX_TEST_TID

SQL> select index_name,uniqueness,tablespace_name  from user_indexes where table_name=upper('test');

INDEX_NAME                     UNIQUENES  TABLESPACE_NAME

------------------------------ ---------  ------------------------------

IDX_TEST_TID                   UNIQUE    FIRSOUL

UK_TEST_TNAME                  UNIQUE    FIRSOUL

PK_TEST_TNO                    UNIQUE    FIRSOUL


在唯一索引上创建唯一约束, TID 列增加了约束,并没有继续增加唯一索引。

SQL> alter table test add constraint uk_test_tid  unique(tid);

Table altered.

SQL> set lines 150

SQL> col table_name for a15

SQL> col column_name for a15

SQL> col constraint_name for a20

SQL> select  table_name,column_name,constraint_name from user_cons_columns where  table_name=upper('test');

TABLE_NAME       COLUMN_NAME     CONSTRAINT_NAME

--------------- --------------- --------------------

TEST             TNO             PK_TEST_TNO

TEST             TNAME           UK_TEST_TNAME

TEST             TID             UK_TEST_TID

SQL> select table_name,column_name,index_name  from user_ind_columns where table_name=upper('test');

TABLE_NAME       COLUMN_NAME     INDEX_NAME

--------------- ---------------  ------------------------------

TEST             TNO             PK_TEST_TNO

TEST            TNAME          UK_TEST_TNAME

TEST             TID             IDX_TEST_TID


通过上边我们可以看出,创建主键、唯一约束时,会同时创建与约束一致名字的索引。
下面我们删除唯一约束,查看效果

SQL>  alter table test drop constraint UK_TEST_TNAME;

 

Table  altered.

 

SQL>  alter table test drop constraint UK_TEST_TID;

 

Table  altered.

 

SQL>  select table_name,column_name,constraint_name from user_cons_columns where  table_name=upper('test');

 

TABLE_NAME      COLUMN_NAME     CONSTRAINT_NAME

---------------  --------------- --------------------

TEST            TNO             PK_TEST_TNO

 

SQL>  select table_name,column_name,index_name from user_ind_columns where  table_name=upper('test');

 

TABLE_NAME      COLUMN_NAME     INDEX_NAME

---------------  --------------- ------------------------------

TEST            TNO             PK_TEST_TNO

TEST            TID             IDX_TEST_TID

  通过上面结果我们可以得知,手动创建索引后再创建约束,删除约束,不会删除索引,创建约束自动创建的索引会在约束失效或删除后自动删除。
 

三、             总结
  通过以上实验我们可以知道

1 、主键约束要求列值非空,而唯一键约束和唯一索引不要求列值非空,都不能有重复数据。

2 、主键约束和唯一键约束会隐式创建同名的唯一索引,当主键约束或者唯一键约束失效时,隐式创建的唯一索引会被删除。

3 、相同字段序列不允许重复创建索引。


请使用浏览器的分享功能分享到微信等