Oracle 約束詳解

2021-08-02 06:40:54 字數 4200 閱讀 5778

約束是資料庫用來確保資料滿足業務規則的手段,不過在真正的企業開發中,除了主鍵約束這類具有強需求的約束,像外來鍵約束,檢查約束更多時候僅僅出現在資料庫設計階段,真實環境卻很少應用,更多是放到程式邏輯中去進行處理。這也比較容易理解,約束會一定程度上較低資料庫效能,有些規則直接在程式邏輯中處理就可以了,同時,也有可能在面對業務變更或是系統擴充套件時,資料庫約束會使得處理不夠方便。不過在我看來,資料庫約束是保證資料準確性的最後一道防線,對於設計合理的系統,處於效能考慮資料庫約束自然可有可無;不過若是面對關聯關係較為複雜的系統,且對系統而言,資料的準確性完整性要高於效能要求,那麼這些約束還是有必要的(否則,就會出現各種相對業務規則來說莫名其妙的髒資料,本人可是深有體會的。。)。總之,對於約束的選擇無所謂合不合理,需要根據業務系統對於準確性和效能要求的側重度來決定。

資料庫約束有五種:

下面我們就分別來看下這五類約束:

[約束語法:]

alter table 表名  

add constraint 約束名  約束型別  具體的約束說明

主鍵約束(primary key)

主鍵是定位表中單個行的方式,可唯一確定表中的某一行,關係型資料庫要求所有表都應該有主鍵,不過oracle沒有遵循此範例要求,oracle中的表可以沒有主鍵(這種情況不多見)。關於主鍵有幾個需要注意的點:

鍵列必須必須具有唯一性,且不能為空,其實主鍵約束相當於 unique+not null

乙個表只允許有乙個主鍵

主鍵所在列必須具有索引(主鍵的唯一約束通過索引來實現),如果不存在,將會在索引新增的時候自動建立

新增主鍵(約束的新增可在建表時建立,也可如下所示在建表後新增,一般推薦建表後新增,靈活度更高一些,建表時新增某些約束會有限制)

sql>

alter

table emp add

constraint pk_id primary

key(id);

唯一性約束(unique)

唯一性約束可作用在單列或多列上,對於這些列或列組合,唯一性約束保證每一行的唯一性。

unique需要注意:

對於unique約束來講,索引是必須的。如果不存在,就自動建立乙個(unique的唯一性本質上是通過索引來保證的)

unique允許null值,unique約束的列可存在多個null。這是因為,unique唯一性通過btree索引來實現,而btree索引中不包含null。當然,這也造成了在where語句中用null值進行過濾會造成全表掃瞄。

新增唯一約束

sql>

alter

table emp add

constraint uq_code unique(code);

非空約束(not null)

非空約束作用的列也叫強制列。顧名思義,強制鍵列中必須有值,當然建表時候若使用default關鍵字指定了預設值,則可不輸入。

新增非空約束,語法較特別

sql>

alter

table emp modify ename not

null;

預設約束(default)

sql

>

alter

table

student modify saddr

default '杭州市西湖區'

;

外來鍵約束(foreign key)

外來鍵約束定義在具有父子關係的子表中,外來鍵約束使得子表中的列對應父表的主鍵列,用以維護資料庫的完整性。不過出於效能和後期的業務系統的擴充套件的考慮,很多時候,外來鍵約束僅出現在資料庫的設計中,實際會放在業務程式中進行處理。外來鍵約束注意以下幾點:

外來鍵約束的子表中的列和對應父表中的列資料型別必須相同,列名可以不同

對應的父表列必須存在主鍵約束(primary key)或唯一約束(unique)

外來鍵約束列允許null值,對應的行就成了孤行了

其實很多時候不使用外來鍵,很多人認為會讓刪除操作比較麻煩,比如要刪除父表中的某條資料,但某個子表中又有對該條資料的引用,這時就會導致刪除失敗。我們有兩種方式來優化這種場景:

第一種方式簡單粗暴,刪除的時候,級聯刪除掉子表中的所有匹配行,在建立外來鍵時,通過 on delete cascade

子句指定該外來鍵列可級聯刪除:

sql>

alter

table emp add

constraint fk_deptno foreign

key(deptno) references dept (deptno) on

delete

cascade;

第二種方式,刪除父表中的對應行,會將對應子表中的所有匹配行的外來鍵約束列置為null,通過 on delete set null子句實施:

sql>

alter

table emp add

constraint fk_deptno foreign

key(deptno) references dept(deptno) on

delete

setnull;

實際上,外來鍵約束列和對應的父表列可以在同一張表中,常見的就是表的業務邏輯含義是一棵樹,最簡單的例子如下(id為主鍵id,fid為父id,fid儲存對id的引用),這種結構的表根據業務要求可通過oracle的遞迴查詢來獲取這種層級關係

檢查約束(check)

檢查約束可用來實施一些簡單的規則,比如列值必須在某個範圍內。檢查的規則必須是乙個結果為true或false 的表示式,比如:

sql>

alter

table emp add

constraint ck_*** check(*** in('

男','

女'));

很多時候由於業務需要,比如我們有大量的歷史資料,需要和現有資料合併,當前表存在資料庫約束(如非空約束),而這些歷史資料又包含違背非空約束的資料行,為了避免匯入時由於違反約束而匯入失敗,我們通過調整約束狀態來達到目的。

資料庫約束有兩類狀態

啟用/禁用(enable/disable)

:是否對新變更的資料啟用約束驗證

驗證/非驗證 (validate/novalidate)

:是否對錶中已客觀存在的資料進行約束驗證

這兩類四種狀態從語法角度講可以隨意組合,預設是 enable validate

下面我們來看著四類組合會分別出現什麼樣的效果:

enable validate

: 預設的約束組合狀態,無法新增違反約束的資料行,資料表中也不能存在違反約束的資料行;

enable novalidate

: 無法新增違反約束的資料行,但對已存在的違反約束的資料行不做驗證;

disable validate

: 可以新增違反約束的資料行,但對已存在的違反約束的資料行會做約束驗證(從描述中可以看出來,這本來就是一種相互矛盾的約束組合,只不過是語法上支援這種組合罷了,造成的結果就是會導致dml失敗)

disable novalidate

: 可以新增違法約束的資料行,對已存在的違反約束的資料行也不做驗證。

拿上面的例子來說,我們需要上傳大量違反非空約束的歷史資料(從業務角度講這些資料不會造成系統功能異常),可以臨時將約束狀態轉為 disable novalidate,以保證這些不合要求的資料匯入表中

sql>

alter

table emp modify constraint emp_ename_nn disable novalidate;

在資料匯入完成之後,我們再將約束狀態轉為enable novalidate 以確保之後新增的資料不會再違反約束

sql>

alter

table emp modify constraint emp_ename_nn enable novalidate;

介紹了資料庫中的五類約束,也提到了資料庫約束的四種狀態組合,當你由於業務需求或是系統擴充套件,在乙個約束嚴苛的系統中由於約束限制頻繁操作失敗的時候,不同組合的約束狀態或許能給你另一種處理方案。

Oracle 約束詳解(constraint)

3 約束分類 1.約束的作用 1 錄入 規範 的資料 2 定義規則 對資料庫中資料進行限制,確保資料正確性 有效性 完整性 1.預設命名 sys cn n 為正整數 2.指定名稱 推薦如下 3.若約束名稱長度超過 30 個位元組,則 表名 使用簡稱 約束型別 規範命名 名稱說明 主鍵約束 pk 表名...

Oracle約束 Constraint 詳解

主鍵約束 primary key 主鍵是定位表中單個行的方式,可唯一確定表中的某一行,關係型資料庫要求所有表都應該有主鍵,不過oracle沒有遵循此範例要求,oracle中的表可以沒有主鍵 這種情況不多見 關於主鍵有幾個需要注意的點 鍵列必須必須具有唯一性,且不能為空,其實主鍵約束 相當於 uniq...

Oracle建立約束 刪除約束

1.定義not null 約束not null 約束只能在列級定義,不能在表級定義 例 create table emp01 eno int not null,name varchar2 10 constraint nn name2 not null,salary number 6,2 2.定義un...