【INDEX】Oracle中主鍵、唯一約束與唯一索引之區別

bitifi發表於2015-09-22
一、            概述

一般在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、相同欄位序列不允許重複建立索引。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30496894/viewspace-1806063/,如需轉載,請註明出處,否則將追究法律責任。

相關文章