数据库完整性约束
完整性約束
????????? ——數據庫完整性約束簡介
- 理解數據庫完整性約束的作用;
- 理解數據庫中的各種約束的作用。
?
- 完整性約束是保證用戶對數據庫所做的修改不會破壞數據的一致性,是保護數據正確性和相容性的一種手段.
?
- 維護完整性
- 在一個DBMS之中,為了能夠維護數據庫的完整性,必須能夠提供以下的幾種支持:
| 提供定義完整性約束條件機制 | 在數據表上定義規則,這些規則是數據庫中的數據必須滿足的語義約束條件; |
| 提供完整性檢查的方法 | 在更新數據庫時檢查更新數據是否滿足完整性約束條件; |
| 違約處理 | DBMS發現數據違反了完整性約束條件后要采取的違約處理行為,如拒絕(NO ACTION)執行該操作,或者級聯(CASCADE)執行其他操作。 |
- 主要約束分類
開發之中可以使用以下的五種約束進行定義:
| 非空約束: | 如果使用了非空約束的話,則以后此字段的內容不允許設置成null; |
| 唯一約束: | 即:此列的內容不允許出現重復; |
| 主鍵約束: | 表示一個唯一的標識,例如:人員ID不能重復,且不能為空; |
| 檢查約束: | 用戶自行編寫設置內容的檢查條件; |
| 主-外鍵約束(參照完整性約束): | 是在兩張表上進行的關聯約束,加入關聯約束之后就產生父子的關系。 |
| 隱式約束 | 例如數據類型 |
?
—— 非空約束:NK
- 在正常情況下,NULL是每個屬性的合法數據值。如果說現在某個字段不能為NULL,且必須存在數據,那么就可以依靠非空約束來進行控制,這樣在數據更新時,此字段的內容出現NULL時就會產生錯誤。
- 非空約束不允許字段為null;
- 非空約束出現錯誤時會提示完整的錯誤位置。
- 使用非空約束:只需要在定義列的時候后面增加一個NOT NULL即可.
|
| DROP TABLE member PURGE ; CREATE TABLE member( ?? mid???? NUMBER?? , ??? name??? VARCHAR2(200)?? NOT NULL ) ; |
|
| INSERT INTO member(mid,name) VALUES(1,'wendy') |
?
—— 唯一約束:UK和CONSTRAINT子句
唯一約束,CONSTRAINT(constraint約束)
- 唯一約束(UNIQUE,簡稱UK)表示的是在表中的數據不允許出現重復的情況
- 唯一約束可以設置NULL;
- 唯一約束的列不允許重復。
- 只需要在定義列的時候后面增加一個UUNIQUE即可.
|
| DROP TABLE member PURGE ; CREATE TABLE member( ??? mid???? NUMBER?? , ??? name??? VARCHAR2(200)?? NOT NULL , ??? email?? VARCHAR2(50)??? UNIQUE ) ; |
| 向表中添加數據: INSERT INTO member(mid,name,email) VALUES(1,'t','z@qq.com') INSERT INTO member(mid,name,email) VALUES(2,'w','z@qq.com') |
| 當添加第二個數據時候出現錯誤:ORA-00001: 違反唯一約束條件 (SCOTT.SYS_C0011099)
|
| 為唯一約束指定一個名字 CONSTRAINT uk_email UNIQUE(email) |
| DROP TABLE member PURGE ; CREATE TABLE member( ??? mid???? NUMBER?? , ??? name??? VARCHAR2(200)??? NOT NULL , ??? email?? VARCHAR2(50)?, ??? CONSTRAINT uk_email????? UNIQUE (email) ) ; |
| 唯一約束是不受空類型控制. 如下兩條記錄都可以執行 |
| INSERT INTO member(mid,name,email) VALUES(1,'t',null) INSERT INTO member(mid,name,email) VALUES(2,'w',null) |
?
主鍵約束:PK
?
- 主鍵約束:PK
- 如果一個字段即要求唯一,又不能設置為null,則可以使用主鍵約束(主鍵約束 = 非空約束 + 唯一約束),
- 主鍵約束使用PRIMARY KEY(簡稱PK)進行指定.
| 在member表中的mid字段應該表示一個成員的唯一編號, 而這個編號即不能為空,也不能重復。 |
| 設置member表中的mid為主鍵 |
| DROP TABLE member PURGE ; CREATE TABLE member( ??? mid???? NUMBER????????? PRIMARY KEY , ??? name??? VARCHAR2(200)?? NOT NULL , ??? email?? VARCHAR2(50)?, ??? CONSTRAINT uk_email UNIQUE (email) ) ; |
| 指定主鍵約束的名稱 |
| DROP TABLE member PURGE ; CREATE TABLE member( ??? mid???? NUMBER?????? , ??? name??? VARCHAR2(200)?? NOT NULL , ??? email?? VARCHAR2(50)?, ??? CONSTRAINT pk_mid PRIMARY KEY (mid) , ??? CONSTRAINT uk_email UNIQUE (email) ) ; |
?
- 復合主鍵
- 在實際的開發之中,一般在一張表中只會設置一個主鍵,但是也允許為一張表設置多個主鍵,這個時候將其稱為復合主鍵。在復合主鍵中,只有兩個主鍵字段的內容完全一樣,才會發生違反約束的錯誤。
不建議使用復合主鍵
?
?? 檢查約束:CK
- 檢查約束指的是對數據增加的條件過濾,表中的每行數據都必須滿足指定的過濾條件。
- 在進行數據更新操作時,如果滿足檢查約束所設置的條件,數據可以成功更新,如果不滿足,則不能更新,
- 在SQL語句中使用CHECK(簡稱CK)設置檢查約束的條件。
- 檢查約束會設置多個過濾條件,所以檢查約束過多時會影響數據更新性能。
- 在member表中增加age字段(年齡范圍是0~200歲)和sex字段(只能是男或女)
DROP TABLE member PURGE ;
CREATE TABLE member(
??? mid???? NUMBER?????? ,
??? name??? VARCHAR2(200)?? NOT NULL ,
??? email?? VARCHAR2(50)?,
??? age???? NUMBER????????? CHECK (age BETWEEN 0 AND 200) ,
??? sex???? VARCHAR2(10) ,
??? CONSTRAINT pk_mid_name PRIMARY KEY (mid,name) ,
??? CONSTRAINT uk_email UNIQUE (email) ,
??? CONSTRAINT ck_sex?? CHECK (sex IN ('男','女'))
) ;
?
主-外鍵約束:FK(重要)
- 級聯操作:ON DELETE CASCADE、ON DELETE SET NULL;
- 使用外鍵約束后刪除表時應先刪除子表再刪除父表;
- 在進行外鍵設置的時候,對應的字段,在父表中必須是主鍵或是唯一約束.
- 如果A表和B表被設置為互為外鍵,那么一張表都無法刪除.
- 這個時候只能強制刪除:DROP TABLE member CASCADE CONSTRAINT;
- 不建議使用,在設計表的時候就應該考慮好先后關系
- 外鍵約束的產生分析
- 例如,現在公司要求每一位成員為公司發展提出一些更好的建議,并且希望將這些建議保存在數據表之中,那么根據這樣的需求,可以設計出如圖所示的設計模型。
- 一個成員可以提出多個建議,這是一個一對多的關系.
- 設計出了兩張數據表,兩張表的作用如下:
- 人員表:用于保存成員的基本信息(編號、姓名);
- 建議表:保存每一個成員提出的建議內容,所以在此表之中保存在了一個成員編號,即:通過此成員編號就可以和成員表進行數據的關聯。
| 建立member和advice表 |
| DROP TABLE member PURGE ; DROP TABLE advice PURGE ; CREATE TABLE member( ??? mid???? NUMBER?????? , ??? name??? VARCHAR2(200)?? NOT NULL , ??? CONSTRAINT pk_mid PRIMARY KEY (mid) ) ; CREATE TABLE advice( ??? adid???? NUMBER?????? , ??? content??? CLOB?? NOT NULL , ??????? mid???? NUMBER, ??? CONSTRAINT pk_adid PRIMARY KEY (adid) ) ; |
| 增加一組正確的數據; WENDY提出了2個意見,GAGA提出了3個意見 |
| INSERT INTO member(mid,name) VALUES(1,'WENDY'); INSERT INTO member(mid,name) VALUES(2,'GAGA'); INSERT INTO advice(adid,content,mid) VALUES(1,'Miss Blair, we must go or we'll be late',1); INSERT INTO advice(adid,content,mid) VALUES(2,'I've been invited to a charity event',1); INSERT INTO advice(adid,content,mid) VALUES(3,'Okay, so whose mess is it?',2); INSERT INTO advice(adid,content,mid) VALUES(4,'Can i borrow you for a minutes?',2); INSERT INTO advice(adid,content,mid) VALUES(5,'There is nothing I can do',2); |
| 查詢每個成員的完整信息和所提出的意見的數量 |
| 確定所需要的數據表: member表 advice表:統計建議數量 確定關聯字段:m.mid=a.mid |
| SELECT m.mid,m.name,COUNT(a.mid) FROM member m,advice a WHERE m.mid=a.mid GROUP BY m.mid,m.name; |
| 增加一個建議,member表中并不存在99的信息,這時候就會出現錯誤數據 |
| INSERT INTO advice(adid,content,mid) VALUES(6,q'[nothing]',99); |
| 現在對于表可以分為父表(member)和子表(advice),因為子表中的數據必須參考member的數據。建議提出的成員編號應該是在member表中mid列上存在的數據. |
| 為了保證表的數據的有效性,只能利用外鍵約束完成. 外鍵使用FOREIGN KEY來進行設置 |
| 增加外鍵配置 |
| DROP TABLE member PURGE ; DROP TABLE advice PURGE ; CREATE TABLE member( ??? mid???? NUMBER?????? , ??? name??? VARCHAR2(200)?? NOT NULL , ?? ?CONSTRAINT pk_mid PRIMARY KEY (mid) ) ; CREATE TABLE advice( ??? adid???? NUMBER?????? , ??? content??? CLOB?? NOT NULL , ??????? mid???? NUMBER, ??? CONSTRAINT pk_adid PRIMARY KEY (adid) , ?CONSTRAINT fk_adid FOREIGN KEY (mid) REFERENCES member(mid) ) ; |
| 執行錯誤的數據插入: INSERT INTO advice(adid,content,mid) VALUES(6,q'[nothing]',99); |
| ORA-02291: 違反完整約束條件 (SCOTT.FK_ADID) - 未找到父項關鍵字 |
?
一旦為表中增加了外鍵約束,就會有新的問題:
級聯操作問題
| 問題一:刪除父表數據前需要先清出所有子表的對應數據 DELECT FROM member WHERE mid=1; |
| RA-02291: 違反完整約束條件 (SCOTT.FK_ADID) - 未找到父項關鍵字。 |
| 如果要刪除這條記錄,就必須要刪除子表的記錄,但是這樣的做法并不可取. |
| DELETE FROM advice WHERE mid=1; DELETE FROM member WHERE mid=1; |
| 解決方法:根據業務需求選擇合適的級聯操作 【級聯操作一】級聯刪除(ON DELETE CASCADE) 當主數據表被刪除后,對應的子表數據也應該同時被清理.這樣不行,比如一個公司部門取消,不能將雇員都刪除. 【級聯操作二】級聯設置NULL(ON DELETE SET NULL) 當主表數據被刪除后,對應的子表數據的相應字段的內容會設置為null. |
| 級聯刪除配置(ON DELETE CASCADE) |
| DROP TABLE advice PURGE ; DROP TABLE member PURGE ; CREATE TABLE member( ??? mid???? NUMBER?????? , ??? name??? VARCHAR2(200)?? NOT NULL , ??? CONSTRAINT pk_mid PRIMARY KEY (mid) ) ; CREATE TABLE advice( ??? adid???? NUMBER?????? , ??? content??? CLOB?? NOT NULL , ??????? mid???? NUMBER, ??? CONSTRAINT pk_adid PRIMARY KEY (adid) , ?CONSTRAINT fk_adid FOREIGN KEY (mid) REFERENCES member(mid) ON DELETE CASCADE ) ; 現在刪除父表記錄,父表記錄以及子表記錄的信息都被刪除. DELETE FROM member WHERE mid=1; |
| 級聯更新:級聯設置NULL(ON DELETE SET NULL) |
| DROP TABLE advice PURGE ; DROP TABLE member PURGE ; CREATE TABLE member( ??? mid???? NUMBER?????? , ??? name??? VARCHAR2(200)?? NOT NULL , ???CONSTRAINT pk_mid PRIMARY KEY (mid) ) ; CREATE TABLE advice( ??? adid???? NUMBER?????? , ??? content??? CLOB?? NOT NULL , ??????? mid???? NUMBER, ??? CONSTRAINT pk_adid PRIMARY KEY (adid) , ?CONSTRAINT fk_adid FOREIGN KEY (mid) REFERENCES member(mid) ON DELETE SET NULL ) ; 刪除父表中的記錄,這個時候父表中的記錄會被刪除,而子表中的記錄會變為null空. DELETE FROM member WHERE mid=1; |
問題二:刪除父表時需要先將子表刪除
?
查看約束
?
- 約束依然屬于數據庫對象,可以直接利用數據字典查看。
- 約束是由數據庫自己創建的兌現個,所有對象都會在數據字典中進行保存
- 可以利用user_constraints數據字典或者user_cons_columns數據字典查看.
| 創建一張member表,主鍵不設置名字 |
| CREATE TABLE member( ??? mid???? NUMBER?????? PRIMARY KEY , ??? name??? VARCHAR2(200)?? NOT NULL , ) ; |
| 向表中插入數據, |
| INSERT INTO member(mid,name) VALUES(1,'WENDY'); INSERT INTO member(mid,name) VALUES(1,'GAGA'); |
| 當插入第二條數據時候會報錯,ORA-00001: 違反唯一約束條件 (SCOTT.SYS_C0011147)
|
| user_constraints查看約束信息,就能看到SYS_C0011099 Constraints_type字段可以看到約束的類型,P為主鍵,C為檢查 |
| SELECT * FROM user_constraints;
SELECT constraint_name,constraint_type,table_name FROM user_constraints ;
SELECT constraint_name,constraint_type,table_name FROM user_constraints WHERE table_name='EMP' ; |
| 要查詢約束所對應的字段,這時候查user_cons_columns |
| SELECT * FROM user_cons_columns; |
?
修改約束(了解)
- 約束在建立表的時候一定要同時建立;
- 對于約束不建議對其進行修改。
?
-
為表中增加約束
- 語法:ALTER TABLE 表名稱 ADD CONSTRAINT 約束名稱 PRIMARY KEY(約束字段) ;
- 范例:為member表的mid字段增加主鍵約束
- ALTER TABLE member ADD CONSTRAINT pk_mid PRIMARY KEY(mid) ;
- 范例:為member表的age增加檢查約束
- ALTER TABLE member ADD CONSTRAINT ck_age CHECK(age BETWEEN 0 AND 200) ;
啟用/禁用約束
- 禁用約束
- ALTER TABLE 表名稱 DISABLE CONSTRAINT 約束名稱 [CASCADE];
- 范例:禁用advice表中的adid主鍵約束“pk_adid”
- ALTER TABLE advice DISABLE CONSTRAINT pk_adid ;
- 啟用約束
- ALTER TABLE 表名稱 ENABLE CONSTRAINT 約束名稱 ;
- 范例:禁用member表中的“pk_mid”約束,此字段在advice表中是外鍵
- ALTER TABLE member DISABLE CONSTRAINT pk_mid ;
- 禁用約束
刪除約束
- ALTER TABLE 表名稱 DROP CONSTRAINT 約束名稱 [CASCADE];
- 范例:刪除advice表之中的“pk_adid”約束 —— 無關聯外鍵
- ALTER TABLE advice DROP CONSTRAINT pk_adid ;
- 范例:刪除member表之中的“pk_mid”約束 —— 有關聯外鍵
- ALTER TABLE member DROP CONSTRAINT pk_mid CASCADE ;
?
?
?
轉載于:https://www.cnblogs.com/thescentedpath/p/constraint.html
總結
- 上一篇: OpenNebula学习第三节之虚拟机管
- 下一篇: Oracle DML