剛開始接觸約束時,可能對它產生了一些困惑,比如說一張表中可以有幾個不同的約束,一張表中的同一列可以有幾個不同的約束,還有約束在列級和表級定義等等問題。
一.約束種類
首先,來看一下約束的種類,ORACLE支持五種類型的完整性約束:
1.NOT NULL (非空)——防止NULL值進入指定的列,在單列基礎上定義,默認情況下,ORACLE允許在任何列中有NULL值;
2.CHECK (檢查)--檢查在約束中指定的條件是否得到了滿足;
3.UNIQUE (唯一)——保證在指定的列中沒有重複值,在該表中每一個值或者每一組值都將是唯一的,但允許NULL插入;
4.PRIMARY KEY (主鍵)——用來唯一的標識出表的每一行,並且防止出現NULL值;
5.FOREIGN KEY (外部鍵)——通過使用公共列在表之間建立一種父子(parent-child)關係。
二.約束的定義
約束的定義分爲列級和表級;
1.對於NOT NULL約束,它只能在列級定義;
如下:
SQL> create table dept(deptno number not null);
Table created.
在表級定義是不正確的:
SQL> create table dept(deptno number(2,0),
2 constraint dept_deptno_notnull not null(deptno));
constraint dept_deptno_notnull not null(deptno))
*
ERROR at line 2:
ORA-00904: : invalid identifier
或者使用alter table 命令來添加約束:
SQL> create table dept(deptno number(2,0));
Table created.
SQL> alter table dept modify deptno not null;
Table altered.
2.對於CHECK約束,它可以在表級和列級定義;
列級定義如下:
SQL> create table dept(deptno number(2,0) constraint dept_deptno_ck check(deptno between 10 and 999));
Table created.
對於表級定義如下:
SQL> create table dept(deptno number(2,0),
2 constraint dept_deptno_ck check(deptno between 10 and 999));
Table created.
或者使用alter table 命令來添加約束:
SQL> create table dept(deptno number(2,0));
Table created.
SQL> alter table dept add constraint dept_deptno_ck check(deptno between 10 and 999);
Table altered.
3.對於UNIQUE約束,它可以在表級和列級定義;
列級定義如下:
SQL> create table dept(deptno number(2,0) constraint dept_deptno_uq unique);
Table created.
對於表級定義如下:
SQL> create table dept(deptno number(2,0),
2 constraint dept_deptno_uq unique(deptno));
Table created.
或者使用alter table 命令來添加約束:
SQL> create table dept(deptno number(2,0));
Table created.
SQL> alter table dept add constraint dept_deptno_uq unique(deptno);
Table altered.
4.對於PRIMARY KEY約束,它可以在表級和列級定義;
列級定義如下:
SQL> create table dept(deptno number(2,0) constraint dept_deptno_pk primary key);
Table created.
對於表級定義如下:
SQL> create table dept(deptno number(2,0) ,
2 constraint dept_deptno_pk primary key(deptno));
Table created.
或者使用alter table 命令來添加約束:
SQL> create table dept(deptno number(2,0));
Table created.
SQL> alter table dept add constraint dept_deptno_pk primary key(deptno);
Table altered.
5.對於FOREIGN KEY約束,它可以在表級和列級定義;
列級定義如下:
SQL> create table dept(deptno number(2,0) constraint dept_deptno_pk primary key);
Table created.
SQL> create table dept1(deptno number(2,0) constraint dept1_deptno_fk references dept(deptno));
Table created.
表級定義如下:
SQL> create table dept(deptno number(2,0) constraint dept_deptno_pk primary key);
Table created.
SQL> create table dept1(deptno number(2,0),
2 constraint dept1_deptno_fk foreign key(deptno) references dept(deptno));
Table created.
或者使用alter table 命令來添加約束:
SQL> create table dept(deptno number(2,0) constraint dept_deptno_pk primary key);
Table created.
SQL> create table dept1(deptno number(2,0));
Table created.
SQL> alter table dept1 add constraint dept1_deptno_fk foreign key(deptno) references dept(deptno);
Table altered.
三.約束問題總結
1.NOT NULL約束,如果要求一組列都具這個約束,則不能爲整個組定義NOT NULL約束,而必須對每個列單獨定義NOT NULL約束;
2.CHECK約束,無法使用子查詢來計算值是否被允許,也無法使用諸如SYSDATE函數;
3.UNIQUE約束,可以對單列或者多列定義,對於多列時,不需要這些列數據類型相同,也 不需要相鄰;
4.PRIMARY KEY約束,可以對單列或者多列定義,它相當於UNIQUE和NOT NULL的組合,但是每個表中只能有一個PK約束,但是可以有任意數量的UNIQUE和NOT NULL的約束列;
5.對於FOREIGN KEY約束,這個約束在子表中定義的列(或者多列)對應父表中的主鍵列。這些列不需要同名,但數據類型必須相同。什麼樣的表可以作爲父表?這個要具有UNIQUE或者是PRIMARY KEY約束的表。FOREIGN KEY約束還有個特點,就是可以插入NULL值,即使在父表中沒有NULL值的情況下。
6.對於開始的問題,一張表中可以有幾個不同的約束,這個可以分爲兩種情況,第一,在表中不同列的約束,如果在不同列有兩個PRIMARY KEY是不允許的,其它情況都是可以的,比如可以一列是PK,一列是UNIQUE。第二,在表中同一列中,如果同一列同時有PRIMARY KEY和UNIQUE是不允許的,其它情況都是可以的,比如這一列既是UNIQUE又是FOREIGN KEY。
7.對於創建約束時自動創建索引問題補充
這個是對上次寫的補充,(主鍵約束自動建立索引問題)
在上面所說的五種約束中,只有PK和UNIQUE約束在創建時,產生唯一性索引,
SQL> create table dept(deptno number(2,0) constraint dept_deptno_pk primary key);
SQL> select index_name from user_indexes;
INDEX_NAME
------------------------------
DEPT_DEPTNO_PK
JHIST_EMP_ID_ST_DATE_PK
JHIST_JOB_IX
可以看到產生了索引;
在dept表deptno列上創建索引,會產生錯誤,是因爲在建立PRIMARY KEY約束時已經創建了索引;
SQL> create index tt on dept(deptno);
create index tt on dept(deptno)
*
ERROR at line 1:
ORA-01408: such column list already indexed
把兩個列作爲主鍵,
SQL> create table dept(deptno number(2,0),dname varchar2(12),constraint deptno_dname_pk primary key(deptno,dname));
Table created.
在上表中的其中一列建立索引,可以成功。
SQL> create index tt on dept(dname);
Index created.