数据库原理学习笔记(一)关系完整性以及数据库完整性
關系完整性是對關系的某種約束,當關系隨著時間變化(增刪改等操作改變數據庫關系表)時應該滿足一定的約束條件,通常這些約束條件都依賴于客觀事實
關系完整性包含三個方面,分別是
- 實體完整性
- 參照完整性
- 用戶自定義完整性
其中實體完整性和參照完整性是關系模型必須滿足的約束條件,或者說是所有數據庫管理系統都自動支持的約束條件。而用戶自定義完整性則是根據不同的應用程序(不同的使用場景)有選擇的設置的一些約束條件
實體完整性
實體完整性實際上就是對于主鍵完整性的約束條件,要求主鍵不能為空(NULL)。如果主鍵為空,那么就無法達到唯一標識一個實體的目的了,所以實體完整性應該包含兩個約束
- 不能為NULL
- 必須唯一,不能重復
實體完整性在SQL語句中使用PRIMARY KEY關鍵字定義(實際上就是在定義主鍵)。有兩種定義方式,一種是在定義屬性的時候將PRIMARY KEY添加到后面,另一種是在定義完所有屬性之后使用關鍵字PRIMARY KEY指出
下面的例子創建一個student表,并將學生id設置為主鍵(用來設置實體完整性約束)
CREATE TABLE student ( id INT PRIMARY KEY, /* 緊跟在屬性定義后面 */name VARCHAR(20) NOT NULL, sex ENUM('male', 'female'), age INT NOT NULL );或者
CREATE TABLE student ( id INT, name VARCHAR(20) NOT NULL, sex ENUM('male', 'female'), age INT NOT NULL ,PRIMARY KEY(id) /* 在定義完所有屬性后設置主鍵 */ );另外,考慮另一個表student_course,它存儲著所有學生的選課信息,只包含學生id和課程id兩個屬性,那么根據客觀事實可知,想要唯一確定這個表中的某一行,就必須同時提供學生id和課程id,也就是說student_course由(學生id,課程id)這個二元組唯一確定,所以它的主鍵應該包含兩個屬性
需要注意的是,當主鍵包含多個字段時,只能采用上述第二種方式定義主鍵,對于student_course的表定義如下
CREATE TABLE student_course ( student_id INT NOT NULL, course_id INT NOT NULL, PRIMARY KEY(student_id, course_id) /* 在所有屬性定義完后定義主鍵 */ );設置之后,當向student表插入數據時,就必須提供一個獨一無二的學生id,任何將學生id設置為NULL或者提供了一個重復的id的操作都會報錯
參照完整性
參照完整性是相對于外鍵而言的,在數據庫中,外鍵常用來關聯兩個表,它的值要么為NULL,要么就是它參照的那個表的主鍵值。以社交網絡系統中的用戶實體和分組實體為例,其中
用戶實體定義了一個用戶的各種信息,包括
- 用戶id
- 密碼
- 個人信息等
好友分組實體定義了一個分組的信息,包括
- 分組id
- 分組名
- 用戶id
這樣在查找每個用戶的所有分組時只需要將兩個表進行聯結并且選擇用戶表的用戶id等于分組表的用戶id的那幾行即可
在上面的設計中,好友分組包含了用戶id,它是用戶表的主鍵,像這樣的屬性被稱為外鍵,它由FOREIGN KEY … REFERENCES關鍵字定義
CREATE TABLE user (user_id INT AUTO_INCREMENT PRIMARY KEY,password VARCHAR(20) NOT NULL, );CREATE TABLE groups ( group_id INT AUTO_INCREMENT, group_name VARCHAR(20) NOT NULL, user_id INT, PRIMARY KEY(group_id, group_name),FOREIGN KEY (user_id) REFERENCES user(user_id) /* 將user_id定為外鍵,參照user表中的user_id屬性 */ );對于外鍵的約束實際上就是對于參照完整性的約束,對于上面的示例而言,groups表中的user_id字段必須在user表中的user_id字段中存在,也就是不能出現在groups中存在一個user_id它在user中沒有的情況
當對表進行插入刪除時,數據庫管理系統會自動檢測該約束規則,常見的情況有兩種
- 向groups表中插入/更新了一行數據,其中的user_id不是user中的數據,就會報錯
- 將user中的某一行數據刪除/更新,而groups中存在將要被刪除/更新那一行的user_id的數據,則操作被拒絕,同樣會報錯
上述的兩種情況被稱為發生了不一致,數據庫管理系統有以下幾種方式可以處理這種問題
- 拒絕執行(NO ACTION),不允許這種情況發生,一旦發送,則會報錯
- 級聯操作(CASCADE),當刪除或更新user表導致發生不一致時,會刪除或更新groups表將不一致消除
- 設置為空值,代替級聯對groups表的刪除和更新操作,將不一致的外鍵值設置為NULL
對于級聯操作,首先重新定義groups表,為外鍵user_id設置級聯
CREATE TABLE groups ( group_id INT AUTO_INCREMENT, group_name VARCHAR(20) NOT NULL,user_id INT, PRIMARY KEY(group_id, group_name), FOREIGN KEY (user_id) REFERENCES user(user_id) ON DELETE CASCADE /* 表示當user表的某個user_id被刪除后,級聯刪除掉groups表對應數據 */ );然后為兩個表添加數據
mysql> SELECT * FROM user; +---------+----------+ | user_id | password | +---------+----------+ | 1 | 1234567 | | 2 | 1234567 | | 3 | 1234567 | +---------+----------+mysql> SELECT * FROM groups; +----------+------------+---------+ | group_id | group_name | user_id | +----------+------------+---------+ | 1 | 1_group1 | 1 | | 1 | 1_group2 | 1 | | 1 | 1_group3 | 1 | | 2 | 2_group1 | 2 | +----------+------------+---------+現在執行刪除操作,刪除user表中user_id為1的元組,然后查看groups表,發現和user_id相關的數據也全部被刪除
mysql> DELETE FROM user WHERE user_id = 1; Query OK, 1 row affected (0.02 sec)mysql> SELECT * FROM groups; +----------+------------+---------+ | group_id | group_name | user_id | +----------+------------+---------+ | 2 | 2_group1 | 2 | +----------+------------+---------+用戶自定義完整性
在CREATE TABLE中定義屬性時,可以根據應用程序的要求在屬性上添加約束條件,即屬性限制,包括
- 列值非空(NOT NULL)
- 列值唯一(UNIQUE)
- 檢查列值是否滿足一個條件表達式(CHECK短語)
比如上述用戶表中的密碼password屬性,很顯然不應該允許用戶不設置密碼,所以在定義這個屬性的時候會加上NOT NULL約束
對于CHECK短語,它可以定義在單個屬性之后,也可以在所有屬性定義完成后再定義,如果是后者,那么條件表達式可以使用任意多個屬性進行判斷
總結
以上是生活随笔為你收集整理的数据库原理学习笔记(一)关系完整性以及数据库完整性的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++代码片段(四)萃取模板类的模板参数
- 下一篇: 数据库原理学习笔记(二)数据库范式