約束是加在表上的一種強制性的規則,是保證數據完整性的一種重要手段。
當向表中插入數據,或修改表中的數據時,必須滿足約束所規定的條件。
在設計表的結構時,應該充分考慮在表上需要施加的約束。
保證數據完整性的方法大致有三種,即應用程序代碼、觸發器和約束。
其中約束是一種更為靈活的方式,它不僅維護更加方便,而且性能也比較高,是保證數據完整性的最佳選擇。
約束可以在創建表時指定,也可以在表創建之後再指定。
如果在表創建之後再指定約束,可能會因為表中已經存在一些數據不滿足這個條件而使得約束無法施加。
約束的類型
在表上可以施加以下五種約束:
•NOT NULL 非空約束
•UNIQUE 唯一性約束
•PRIMARY KEY 主鍵約束
•FOREIFN KEY 外鍵約束
•CHECK 檢查約束
NOT NULL約束規定一個列上的值不能為空。
當使用INSERT語句向表中插入一行數據,或者使用UPDATE語句修改一行數據時,必須為該列指定值,不能使其為空。
UNIQUE約束規定一個列上的數據必須唯一,不能有重復值,但是允許為空值。
PRIMARY KEY約束是主鍵約束。
CREATE TABLE test (
empno NUMBER PRIMARY KEY,
ename VARCHAR2(10) NOT NULL,
job VARCHAR2(9) UNIQUE,
sal NUMBER CHECK(sal>0),
deptno NUMBER REFERENCES dept
);
注:
主鍵用來唯一地標識表中的一行數據,它規定在主鍵列上的數據不能重復,並且不能為空。
每個設計合理的表都應該有一個主鍵。主鍵可以是一個列,也可以是多個列的組合。
如果在某個列上指定了主鍵約束,那麼就不需要在該列上再指定NOTNULL 約束和UNIQUE約束了。
在一個表上只能創建一個主鍵。
當創建主鍵時,在主鍵列上將自動建立一個唯一性索引,索引的名字與約束的名字相同。
FOREIFN KEY為外鍵約束。
外鍵用來與另一個表建立關聯關系。
兩個表之間的關聯關系是通過主鍵和外鍵來維持的。
外鍵規定該列中的數據必須是另一個與之關聯的表中的主鍵列中的數據。
外鍵可以是一個列,也可以是多個列的組合。
在一個表中只能有一個主鍵,但是可以有多個外鍵。
檢查約束是一個關系表達式,它規定了一個列必須滿足的條件。
注:主鍵約束和外鍵約束都會隱式的創建唯一性索引,索引名稱與約束名稱相同。
反之,創建唯一性索引時,也會隱式的創建唯一性約束。
如何在創建表時指定約束
如果與表同時創建,那麼在創建表的CREATE語句中通過CONSTRAINT關鍵字指定約束的名稱和約束類型。
同時創建表和約束的CREATE語句格式為:
CREATE TABLE 表名(
列1 數據類型CONSTRAINT 約束名1 約束類型,
列2 數據類型CONSTRAINT 約束名2 約束類型,
...
);
其中約束名是為約束指定的唯一的名稱。
約束名可以由用戶自己指定,也可以自動產生。
如果省略關鍵字CONSTRAINT和約束名稱,那麼約束名稱將自動產生。
如果約束名稱是自動產生的,那麼根據這樣的名稱無法判斷約束所在的表以及約束類型。
如果用戶自己指定約束名稱,則可以在名稱中包含表名、約束類型等有用信息。
如果在一個列的定義之後指定該列上的約束時,這種定義約束的方法稱為列級約束。
約束可以在每個列的定義之後分別指定,也可以在所有列的定義之後一起指定。
如果一個約束在表定義的最後才指定,這樣的約束定義方法稱為表級約束。
如果一個約束涉及多個列的組合,那麼就不能在每個列之後指定約束,而只能定義為表級約束。
定義表級約束的CREATE語句格式為:
CREATE TABLE 表名(
列 1 數據類型,
列 2 數據類型,
··
CONSTRAINT 約束名l 約束類型(列名),
CONSTRAINT 約束名2約束類型(列名),
. . . );
在五種約束中, NOT NULL約束只能以列級約束的形式定義,其余四種既可以以列級約束的形式定義,也可以以表級約束的形式定義因為表級約束是在所有列之後定義的,而不是在某個具體的列之後定義,所以在表級約束中要指定相關的列名。
外鍵約束的定義形式比較復雜,因為外鍵要與另一個表的主鍵進行關聯,所以不僅要指定約束的類型和有關的列,還要指定與哪個表的哪個列進行關聯。
如果在列級定義外鍵約束,定義的格式為:
CONSTRAINT 約束名 REFERENCES 表名(列名);
其中約束名是為這個外鍵約束起的名字。
FOREIGN KEY 為約束類型,即外鍵約束。
REFERENCES關鍵字指定與哪個表的哪個列進行關聯。
如果要在表級定義外鍵約束,那麼外鍵的定義代碼放置在所有列的定義之後,它的格式為:
CONSTRAINT 約束名 FOREIGN KEY(外鍵列) REFERENCES 表名(列名);
約束作為一種附加在表上的數據庫對象,它的信息也被記錄在數據字典中。
與約束有關的數據字典有兩個,一個是user_constraints,另一個是user_cons_columns 。
其中在數據字典user_constraints 中記錄當前用戶所擁有的約束的信息,如約束名、約束類型、約束所在的表、約束的狀態等。
如果是外鍵,還記錄了與之關聯的主鍵名稱。
數據字典視圖USER_CONSTRAINTS各列及其意義如下:
OWNER (Owner of the table)
CONSTRAINT_NAME (Name associated(關聯) with constraint definition)
CONSTRAINT_TYPE (Type of constraint definition)
TABLE_NAME (Name associated with table with constraint definition)
SEARCH_CONDITION (Text of search condition for table check)
R_OWNER (Owner of table used in referential constraint)
R_CONSTRAINT_NAME (Name of unique constraint definition for referenced table)
DELETE_RULE (The delete rule for a referential constraint)
STATUS (Enforcement status of constraint - ENABLED or DISABLED)
DEFERRABLE (Is the constraint deferrable - DEFERRABLE or NOT DEFERRABLE)
DEFERRED (Is the constraint deferred(延遲約束) by default - DEFERRED or IMMEDIATE)
VALIDATED (Was this constraint system validated(驗證)? - VALIDATED or NOT VALIDATED)
GENERATED (Was the constraint name system generated(產生)? - GENERATED NAME or USER NAME)
BAD (Creating this constraint should give ORA-02436. Rewrite it before 2000 AD. )
RELY (If set, this flag will be used in optimizer(查詢優化器))
LAST_CHANGE (The date when this column was last enabled or disabled)
INDEX_OWNER (The owner of the index used by the constraint)
INDEX_NAME (The index used by the constraint)
INVALID (無效的)
VIEW_RELATED (有關)
如果要進一步查詢約束施加在哪個列上,就需要查詢另一個數據字典了,它就是USER_ CONS_ COLUMNS 。
數據字典視圖USER_CONS_COLUMNS各列及其意義如下:
OWNER (Owner of the constraint definition)
CONSTRAINT_NAME (Name associated with the constraint definition)
TABLE_NAME (Name associated with table with constraint definition)
COLUMN_NAME (Name associated with column or attribute of object column specified in the constraint definition)
POSITION (Original position of column or attribute in definition)
如何在創建表之後指定約束
在表創建之後再添加約束可能會帶來這樣的問題,如果表中已經有數據而這樣的數據不滿足將要添加的約束,那麼約束是無法添加的。
因此最好的做法是在創建表之前充分考慮需要什麼樣的約束,在創建表的同時定義約束。
添加約束實際上也是對表的修改,因此添加約束也是通過執行ALTER語句完成的。
添加約束的ALTER語句格式為:
ALTER TABLE 表名稱 ADD (CONSTRAINT 約束名稱 約束類型 (列名稱), CONSTRAINT 約束類型 (列名稱));
如果要添加多個約束,在ADD子句的括號中指定多個用逗號分割的約束就好了。
除了NOT NULL之外,其他四個約束都可以通過ADD子句添加。
NOT NULL約束比較特殊,只能通過ALTER命令的MODIFY子句來添加。
添加NOT NULL子句約束的語法格式為:
ALTER TABLE 表名稱 MODIFY 列名稱 CONSTAINT 約束名稱 NOT NULL;
約束的維護
如果希望去掉表上的某個約束,可以將其刪除,也可以使其無效。
約束是不能被修改的,如果在表上已經建立了一個約束,現在希望把它改為另一種類型的約束,或者希望把它施加到另一個列上,只能先將這個約束刪除,然後重新創建。
刪除約束是通過執行ALTER命令的DROP子句來實現的。
刪除約束的ALTER語句的語法格式為:
ALTER TABLE 表名稱 DROP CONSTRAINT 約束名稱;
如果要刪除一個主鍵約束,首先要考慮這個主鍵列是否已經被另一個表的外鍵所關聯,如果沒有關聯,可以直接刪除,如果有關聯,則不能直接刪除。
要刪除主鍵約束,必須使用CASCADE關鍵字,連同與之關聯的外鍵約束一起刪除。
刪除主鍵約束的ALTER語句的語法格式為:
ALTER TABLE 表名稱 DROP CONSTRAINT 主鍵約束名稱 CASCADE;
在表中建立主鍵約束或UNIQUE約束時,在相關的列上將自動添加唯一性索引。
當從表中刪除主鍵約束或UNIQUE約束時,與它們相關的索引也被刪除。
如果希望一個約束暫時不起作用,可以使其無效。
使約束無效的操作是通過ALTER命令的DISABLE子句實現的。
使約束無效的ALTER命令格式為:
ALTER TABLE 表名稱 DISABLE CONSTRAINT 約束名稱;
如果希望一個約束重新有效,可以執行帶ENABLE的ALTER語句。
這時ALTER命令的格式為:
ALTER TABLE 表名稱 ENABLE CONSTRAINT 約束名稱;