SQL - 約束條件:數據完整性的關鍵

你好,未來的數據魔法師們!我很興奮能夠成為你們在 SQL 約束世界中的引路人。作為一個教學 SQL 超過十年的老師,我可以向你們保證,理解約束條件就像是解鎖數據庫管理中的秘密超能力。那麼,我們來一起深入探討吧!

SQL - Constraints

SQL 約束是什麼?

想像你正在建造一個紙牌房子。每一張紙牌都需要精確放置,否則整個結構可能會倒塌。SQL 約束就像是讓你的數據庫「紙牌房子」穩固站立的規則。它們保證表中的數據遵循特定的規則,以保持準確性和一致性。

為什麼約束條件很重要?

讓我分享一個快速的故事。我曾經有一個學生,為一家寵物店建立了一個數據庫,沒有使用約束條件。有一天,他不小心為一隻小狗輸入了一個負數價格。突然之間,人們得到了領養狗的報酬!這場混亂(但狗們很開心)。這就是為什麼我們需要約束條件——來防止這些既滑稽又麻煩的情況。

SQL 約束:陣容介紹

這裡是我們將要探討的主要 SQL 約束的表格:

約束 描述
NOT NULL 保證列不能有 NULL 值
UNIQUE 保證列中的所有值都是不同的
PRIMARY KEY NOT NULL 和 UNIQUE 的組合
FOREIGN KEY 保證表之間的引用完整性
CHECK 保證列中的所有值滿足特定條件
DEFAULT 為列設置默認值
INDEX 用於快速創建和從數據庫中检索數據

現在,我們來一一解析這些約束。

在 SQL 中創建約束

約束可以在創建表的時候添加,或者稍後使用 ALTER TABLE 語句添加。我們先從為我們想像中的寵物店創建一個簡單的表開始:

CREATE TABLE pets (
id INT NOT NULL PRIMARY KEY,
name VARCHAR(50) NOT NULL,
species VARCHAR(50) NOT NULL,
age INT CHECK (age >= 0),
price DECIMAL(10, 2) NOT NULL CHECK (price > 0),
adoption_date DATE DEFAULT NULL
);

這個簡單的表已經包含了多個約束。讓我們來一一解析它們:

NOT NULL 約束

NOT NULL 約束保證列不能有 NULL 值。在我們的例子中,'id'、'name'、'species' 和 'price' 都是 NOT NULL。這意味著每隻寵物必須填寫這些詳細信息。

name VARCHAR(50) NOT NULL,

UNIQUE 鍵約束

雖然我們在這裡沒有顯式使用 UNIQUE,但它值得一提。UNIQUE 約束保證列中的所有值都是不同的。例如,如果我們想要每隻寵物都有唯一的微晶片編號:

ALTER TABLE pets
ADD COLUMN microchip_number VARCHAR(20) UNIQUE;

DEFAULT 值約束

DEFAULT 約束為列提供了一個默認值,當沒有指定值時。在我們的例子中,'adoption_date' 有一个 DEFAULT 為 NULL,意味著如果沒有提供日期,它將是 NULL。

adoption_date DATE DEFAULT NULL

PRIMARY KEY 約束

PRIMARY KEY 約束唯一標識表中的每條記錄。它結合了 NOT NULL 和 UNIQUE。在我們的表中,'id' 是主鍵:

id INT NOT NULL PRIMARY KEY,

FOREIGN KEY 約束

FOREIGN KEY 約束用於防止會破壞表之間鏈接的操作。讓我們添加一個主人表並將其與我們的寵物表鏈接:

CREATE TABLE owners (
owner_id INT NOT NULL PRIMARY KEY,
name VARCHAR(100) NOT NULL
);

ALTER TABLE pets
ADD COLUMN owner_id INT,
ADD CONSTRAINT fk_owner
FOREIGN KEY (owner_id) REFERENCES owners(owner_id);

現在,你不能添加一個不存在於主人表中的 owner_id 的寵物。這就像確保每隻寵物都有真正的家!

CHECK 值約束

CHECK 約束保證列中的所有值滿足特定條件。在我們的寵物表中,我們用它來確保年齡和價格是正數:

age INT CHECK (age >= 0),
price DECIMAL(10, 2) NOT NULL CHECK (price > 0),

INDEX 約束

雖然不完全是約束,但 INDEX 對數據庫性能至關重要。它們就像書後的索引,幫助 SQL 快速找到數據:

CREATE INDEX idx_species ON pets(species);

這在物種列上創建了一個索引,使得按物種搜索更快。

刪除 SQL 約束

有時候,你可能需要移除一個約束。這樣做的方法如下:

ALTER TABLE pets
DROP CONSTRAINT check_price;

這將移除價格列上的 CHECK 約束。

數據完整性約束:將一切整合起來

所有的這些約束一起工作,以確保數據完整性。它們就像是數據庫的免疫系統,保護它免受不良數據的侵害。讓我們看一個更複雜的例子:

CREATE TABLE adoptions (
adoption_id INT NOT NULL PRIMARY KEY,
pet_id INT NOT NULL,
owner_id INT NOT NULL,
adoption_date DATE DEFAULT CURRENT_DATE,
adoption_fee DECIMAL(10, 2) CHECK (adoption_fee >= 0),
FOREIGN KEY (pet_id) REFERENCES pets(id),
FOREIGN KEY (owner_id) REFERENCES owners(owner_id),
UNIQUE (pet_id, adoption_date)
);

這個表保證:

  1. 每次領養都有唯一的 ID(PRIMARY KEY)
  2. 每次領養都與有效的寵物和主人鏈接(FOREIGN KEY)
  3. 領養費用不能為負(CHECK)
  4. 如果沒有指定領養日期,則默認為今天(DEFAULT)
  5. 同一天內一隻寵物不能被領養兩次(UNIQUE 組合)

就这样!你现在已經有了使用 SQL 約束保持數據庫乾淨、一致和無錯誤的充分装备。記住,一個約束良好的數據庫是一個快樂的數據庫。快樂編程,未來的數據大師!

Credits: Image by storyset