oracle 的限制主要是在業務邏輯層面維護資料的完整性。主要透過程式設計師在應用程式中規定約束或透過定義觸發器來維護資料完整性,最後是透過使用oracle自帶的約束來維護資料完整性。能使用oracle自帶的約束達到要求就盡量使用oracle自帶的約束,因為使用觸發器等用戶自訂約束都會影響資料庫的效能。例如:使用觸發器時會對資料表進行鎖定並進行資料表掃描或索引掃描,這些都會降低資料庫效能和並發性。
oracle 約束主要分為以下幾種:
not null 非空約束, unique 唯一約束, primary key 主鍵約束, foreign key 外鍵約束, check 約束。
not null 非空約束:
建立方式:1, 建表時在列層級定義(也就是只能在定義表時將約束的定義寫在該列後面),2種方式。一種使用自訂約束名稱,一種是使用系統預設名稱。
view plaincopy to clipboardprint?
create table t
(
tid number(8) constraint NK_t1 not null,
tname varchar2(10) not null
)
create table t
(
tid number(8) constraint NK_t1 not null,
tname varchar2(10) not null
)
view plaincopy to clipboardprint?
SQL> select t.constraint_name, t.table_name, t.status, t.deferrable from user_constraints t;
CONSTRAINT_NAME TABLE_NAME STATUS DEFERRABLE
--------------- ------------------------------ ----- --- --------------
NK_T1 T ENABLED NOT DEFERRABLE
SYS_C003735 T ENABLED NOT DEFERRABLE
SQL>
SQL> select t.constraint_name, t.table_name, t.status, t.deferrable from user_constraints t;
CONSTRAINT_NAME TABLE_NAME STATUS DEFERRABLE
--------------- ------------------------------ ----- --- --------------
NK_T1 T ENABLED NOT DEFERRABLE
SYS_C003735 T ENABLED NOT DEFERRABLE
SQL>
2,在表建立後對表進行修改,但是要確保表中資料沒有違反約束。
view plaincopy to clipboardprint?
SQL> alter table t modify tid not null;
Table altered
SQL> select t.constraint_name, t.table_name, t.status, t.deferrable from user_constraints t;
CONSTRAINT_NAME TABLE_NAME STATUS DEFERRABLE
--------------- ------------------------------ ----- --- --------------
SYS_C003736 T ENABLED NOT DEFERRABLE
SQL>
SQL> alter table t modify tid not null;
Table altered
SQL> select t.constraint_name, t.table_name, t.status, t.deferrable from user_constraints t;
CONSTRAINT_NAME TABLE_NAME STATUS DEFERRABLE
--------------- ------------------------------ ----- --- --------------
SYS_C003736 T ENABLED NOT DEFERRABLE
SQL>
check 約束
建立方式:可以在表格層級和列層級進行定義(既可以在列後面定義也可以在列定義完後再定義)。也是2種定義方式。
view plaincopy to clipboardprint?
SQL> create table t
2 (
3 tid number(8) ,
4 tname varchar2(10),
5 constraint CK_T1 check ((tid is not null) and (tid > 0))
6 )
7 /
Table created
SQL> alter table t add constraint CK_T2 check(tname is not null);
Table altered
SQL> select t.constraint_name, t.table_name, t.status, t.deferrable from user_constraints t;
CONSTRAINT_NAME TABLE_NAME STATUS DEFERRABLE
--------------- ------------------------------ ----- --- --------------
CK_T1 T ENABLED NOT DEFERRABLE
CK_T2 T ENABLED NOT DEFERRABLE
SQL>
SQL> create table t
2 (
3 tid number(8) ,
4 tname varchar2(10),
5 constraint CK_T1 check ((tid is not null) and (tid > 0))
6 )
7 /
Table created
SQL> alter table t add constraint CK_T2 check(tname is not null);
Table altered
SQL> select t.constraint_name, t.table_name, t.status, t.deferrable from user_constraints t;
CONSTRAINT_NAME TABLE_NAME STATUS DEFERRABLE
--------------- ------------------------------ ----- --- --------------
CK_T1 T ENABLED NOT DEFERRABLE
CK_T2 T ENABLED NOT DEFERRABLE
SQL>
約束CK_T1保證tid欄位不能為空且大於0,CK_T2保證iname不能為空。 check約束也可以是同一行的不同欄位之間的規則。
unique 約束
建立方式:單unique規定的欄位只有一列時可以在列層級定義,如果unique規定的欄位包含多個欄位時只能在表格層級定義。
view plaincopy to clipboardprint?
SQL> create table t2
2 (
3 vid number constraint VK_T1 unique,
4 vname varchar2(10),
5 vsex varchar2(10),
6 constraint VK_T2 unique(vname,vsex)
7 )
8 /
Table created
SQL> select t.constraint_name, t.table_name, t.status, t.validated, t.deferrable from user_constraints t;
CONSTRAINT_NAME TABLE_NAME STATUS VALIDATED DEFERRABLE
--------------- ---------- -------- ---------- ------- -------
VK_T1 T2 ENABLED VALIDATED NOT DEFERRABLE
VK_T2 T2 ENABLED VALIDATED NOT DEFERRABLE
SQL>
SQL> create table t2
2 (
3 vid number constraint VK_T1 unique,
4 vname varchar2(10),
5 vsex varchar2(10),
6 constraint VK_T2 unique(vname,vsex)
7 )
8 /
Table created
SQL> select t.constraint_name, t.table_name, t.status, t.validated, t.deferrable from user_constraints t;
CONSTRAINT_NAME TABLE_NAME STATUS VALIDATED DEFERRABLE
--------------- ---------- -------- ---------- ------- -------
VK_T1 T2 ENABLED VALIDATED NOT DEFERRABLE
VK_T2 T2 ENABLED VALIDATED NOT DEFERRABLE
SQL>
unique約束創建的同時會產生一條索引(可能是唯一性所以也可以是非唯一性索引,這要看建表時指定該表是否在資料插入時立即檢查資料的約束):
view plaincopy to clipboardprint?
SQL> select t.index_name, t.table_name, t.uniqueness from user_indexes t;
INDEX_NAME TABLE_NAME UNIQUENESS
----------- ---------- ----------
VK_T1 T2 UNIQUE
VK_T2 T2 UNIQUE
SQL> select t.index_name, t.table_name, t.uniqueness from user_indexes t;
INDEX_NAME TABLE_NAME UNIQUENESS
----------- ---------- ----------
VK_T1 T2 UNIQUE
VK_T2 T2 UNIQUE
由於有索引所以在建立表格時可以指定索引儲存的位置和一些儲存參數。
view plaincopy to clipboardprint?
SQL> create table t2
2 (
3 vid number constraint VK_T1 unique,
4 vname varchar2(10),
5 vsex varchar2(10),
6 constraint VK_T2 unique(vname,vsex) using index tablespace indx
7 storage(initial 100k next 100k pctincrease 0)
8 nologging
9 )
10 /
Table created
SQL> create table t2
2 (
3 vid number constraint VK_T1 unique,
4 vname varchar2(10),
5 vsex varchar2(10),
6 constraint VK_T2 unique(vname,vsex) using index tablespace indx
7 storage(initial 100k next 100k pctincrease 0)
8 nologging
9 )
10 /
Table created
指定約束索引儲存的表空間是indx表空間,初始區塊大小是100k,然後對dml操作不產生日誌(但是由於其他原因也會產生日誌,只是相對預設的logging要少)
primary key 主鍵約束
創建方式:primary key主要是由非空和唯一性組合而成的。一個表只能包含一個主鍵,但一個主鍵可以含有多個列。
view plaincopy to clipboardprint?
SQL> create table t2
2 (
3 vid number constraint VK_T1 unique,
4 vname varchar2(10),
5 vsex varchar2(10),
6 constraint VK_T2 primary key(vname,vsex) using index tablespace indx
7 storage(initial 100k next 100k pctincrease 0)
8 nologging
9 )
10 /
Table created
SQL> create table t2
2 (
3 vid number constraint VK_T1 unique,
4 vname varchar2(10),
5 vsex varchar2(10),
6 constraint VK_T2 primary key(vname,vsex) using index tablespace indx
7 storage(initial 100k next 100k pctincrease 0)
8 nologging
9 )
10 /
Table created
foreign key 外鍵
建立方式:外鍵涉及的表可以有2張也可以是1張,2張的情況下一張child表中的一個字段引用的鍵必須fater表中的主鍵。約束是建立在child表中的,標示該表中的該欄位中的值必須在父表中存在或是NULL值。
view plaincopy to clipboardprint?
SQL> create table dept
2 (
3 did number(8),
4 dname varchar2(20),
5 constraint PK_DEPT primary key (did)
6 )
7 /
Table created
SQL>
SQL> create table emp
2 (
3 eid number(8) primary key,
4 ename varchar2(20),
5 did number(8) /*references dept(did)*/,
6 dname varchar2(20),
7 constraint FK_EMP2 foreign key(did) references dept(did)
8 )
9 /
Table created
SQL> create table dept
2 (
3 did number(8),
4 dname varchar2(20),
5 constraint PK_DEPT primary key (did)
6 )
7 /
Table created
SQL>
SQL> create table emp
2 (
3 eid number(8) primary key,
4 ename varchar2(20),
5 did number(8) /*references dept(did)*/,
6 dname varchar2(20),
7 constraint FK_EMP2 foreign key(did) references dept(did)
8 )
9 /
Table created
由於外鍵(foreign key)由reference key(引用鍵)決定所以在對fater table進行update或drop,delete等操作時會受到限制。具體有外鍵約束的狀態決定。
delete on action, delete cascade, delete set null
delete on action 預設設置,如果刪除fater table表中的數據,這時oracle會鎖定字表然後進行掃描表(如果外鍵列有所以則掃描索引)然後child表中的外鍵列存在該數據則不允許刪除。
delete cascade 則把字表中的對應對應的行也刪除。
delete set null 則吧子表中的外鍵列對應的資料變成NULL.
view plaincopy to clipboardprint?
create table emp
(
eid number(8) primary key,
ename varchar2(20),
did number(8) /*references dept(did)*/,
dname varchar2(20),
constraint FK_EMP2 foreign key(did) references dept(did) on delete set null
)
create table emp
(
eid number(8) primary key,
ename varchar2(20),
did number(8) /*references dept(did)*/,
dname varchar2(20),
constraint FK_EMP2 foreign key(did) references dept(did) on delete set null
)