MySQL之完整性約束

文章轉自:原文地址

我們知道,一種數據模型必須包含三個基本的部分:

  • 構造機制(數據結構):主要描述數據的類型、內容、性質以及數據間的聯繫等。
  • 運算機制(數據操作):主要描述在相應的數據結構上的操作類型和操作方式。
  • 約束機制(數據約束):主要描述數據結構內數據間的語法、詞義聯繫、他們之間的制約和依存關係,以及數據動態變化的規則,以保證數據的正確、有效和相容。

作爲數據庫的一種數據模型,關係模型提供了一組完整性規則或限制。完整性約束用於確定關係數據庫裏數據的準確性和一致性。

在關係型數據庫裏,完整性約束包括域完整性實體完整性引用完整性以及用戶定義完整性

一、完整性約束的概念

1.1 域完整性

域完整性,是指給定列的取值範圍(即輸入的有效性),比如性別取值應爲男或女。

強制域有效性的方法有:限制類型(通過數據類型)、格式(通過 CHECK 約束和規則)或可能值的範圍(通過 FOREIGN KEY 約束、CHECK 約束、DEFAULT 定義、NOT NULL 定義和規則)。

1.2 實體完整性

實體完整性,是指使用主鍵來唯一地標識一個實體。

在關係數據庫中,一條記錄代表一個實體。而實體是可以相互區分、識別的,也即它們應具有某種唯一性標識(該標識不能取相同的值,也不能爲空)。

實體完整性強制表的標識符列或主鍵的完整性(通過索引、UNIQUE 約束、PRIMARY KEY 約束或 IDENTITY 屬性)。

1.3 引用完整性

引用完整性,就是定義外鍵與主鍵之間的引用規則。

假設有兩個關係:

Student (stuID, name, sex, age, classID);
Class (classID, amount, teacherName);
  • 1
  • 2
  • 1
  • 2

其中 classID 是關係 Student 的外鍵,它引用了關係 Class 裏的 classID。這個外鍵確保了關係 Student 裏的每個 classID 都在關係 Class 中有對應的 classID。在輸入或刪除記錄時,引用完整性保持表之間已定義的關係:

  • 爲了在 Student 中插入一條記錄,其 classID 首先要存在於 Class 中。
  • 在 Class 中刪除一條記錄,則 Student 中 classID 值對應的記錄必須全部被刪除。

引用完整性基於外鍵與主鍵之間或外鍵與唯一鍵之間的關係(通過 FOREIGN KEY 和 CHECK 約束)。引用完整性確保鍵值在所有表中一致。這樣的一致性要求不能引用不存在的值,如果鍵值更改了,那麼在整個數據庫中,對該鍵值的所有引用要進行一致的更改。

1.4 用戶定義完整性

用戶定義完整性讓用戶可以定義不屬於其它任何完整性分類的特定業務規則。所有的完整性類型都支持用戶定義完整性(CREATE TABLE 中的所有列級和表級約束、存儲過程和觸發器)。

二、MySQL中的約束

不同的數據庫產品對完整性約束的支持程度不一樣,但基本的完整性約束都是支持的。相信以後會越來越完善。

2.1 主鍵約束

主鍵,又稱主碼,是表中一列或多列的組合,能夠唯一地標識表中的一條記錄。主鍵約束(Primary Key Constraint)要求主鍵列的數據唯一,且不允許爲空。

在創建表的過程中添加一個字段的主鍵約束:

CREATE TABLE employees (
    id INT(11) AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(20) NOT NULL,
    deptId INT(3) NOT NULL,
    salary FLOAT NOT NULL
);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
CREATE TABLE employees (
    id INT(11) AUTO_INCREMENT,
    name VARCHAR(20) NOT NULL,
    deptId INT(3) NOT NULL,
    salary FLOAT NOT NULL,
    PRIMARY KEY(id)
);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

注意:AUTO_INCREMENT表示自增,默認初始值爲1。

也可以使用多個字段的組合作爲主鍵:

CREATE TABLE employees (
    name VARCHAR(20) NOT NULL,
    deptId INT(3) NOT NULL,
    salary FLOAT NOT NULL,
    PRIMARY KEY(name, deptId)
);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

另外,也可以在建表之後使用ALTER添加主鍵約束:

CREATE TABLE employees (
    name VARCHAR(20) NOT NULL,
    deptId INT(3) NOT NULL,
    salary FLOAT NOT NULL,
);

ALTER TABLE employees ADD CONSTRAINT emp_pk PRIMARY KEY(name, deptId);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2.2 唯一性約束

唯一性約束(Unique Constraint)要求表裏某個字段的值在每條記錄裏都是唯一的,這一點與主鍵類似。聲明爲 UNIQUE 的字段允許爲空,但只能出現一個空值。

CREATE TABLE department(
    deptId INT(3) PRIMARY KEY,
    name VARCHAR(20) UNIQUE,
    location VARCHAR(50)
);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5
CREATE TABLE department(
    deptId INT(3) PRIMARY KEY,
    name VARCHAR(20),
    location VARCHAR(50),
    UNIQUE(name)
);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2.3 外鍵約束

外鍵(Foreign Key):首先它是表中的一個字段,它可以不是本表的主鍵,但必須對應另外一個表的主鍵。外鍵可以爲空值,若不爲空值,則每一個外鍵值必須等於另一個表中主鍵的某個值。

外鍵約束是確保表與表之間引用完整性的主要機制。一個表可以有一個或多個外鍵。通常,我們把外鍵所在的表稱爲子表,外鍵所引用的表稱爲父表

CREATE TABLE employees(
    id INT(11) PRIMARY KEY,
    name VARCHAR(20) NOT NULL,
    deptId INT(3) NOT NULL,
    salary FLOAT NOT NULL,
    CONSTRAINT emp_fk FOREIGN KEY(deptId) REFERENCES department(deptId)
);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

或者

ALTER TABLE employees ADD CONSTRAINT emp_fk FOREIGN KEY(deptId) REFERENCES department(deptId);
  • 1
  • 1

2.4 非空約束

非空約束(Not Null Constraint)指字段的值不能爲空。對於使用了 NOT NULL 約束的字段,如果用戶在添加數據時沒有指定值,數據庫系統會報錯。

CREATE TABLE employees (
    id INT(11) PRIMARY KEY,
    name VARCHAR(20),
    deptId INT(3),
    salary FLOAT
);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

添加非空約束:

ALTER TABLE employees MODIFY name varchar(20) NOT NULL;
  • 1
  • 1

取消非空,並添加默認值:

ALTER TABLE employees MODIFY name varchar(20) DEFAULT 'abc';
  • 1
  • 1

2.5 檢查約束

檢查約束(Check Constraint)用於檢查輸入到特定字段的數據的有效性。MySQL不支持check約束,但可以使用check約束,而沒有任何效果。

CREATE TABLE employees (
    id INT(11) PRIMARY KEY,
    name VARCHAR(20),
    age INT(3),
    CONSTRAINT age_chk CHECK(age>18)
);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

上面 check 約束要求 age 必須大於18,但插入數據時卻沒有起到任何作用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章