在 MySQL 中,CONSTRAINT 關(guān)鍵字用于定義數(shù)據(jù)完整性約束,確保表中數(shù)據(jù)符合特定規(guī)則。通過(guò) CONSTRAINT,你可以顯式命名約束,使其更易管理和維護(hù)。以下是詳細(xì)用法和示例:
一、CONSTRAINT 的作用
- 顯式命名約束:為約束規(guī)則指定名稱,方便后續(xù)修改或刪除。
- 數(shù)據(jù)完整性:強(qiáng)制數(shù)據(jù)滿足業(yè)務(wù)規(guī)則(如唯一性、關(guān)聯(lián)性、范圍限制等)。
- 統(tǒng)一管理:在多列約束或跨表關(guān)聯(lián)時(shí),命名約束更清晰。
二、核心約束類型及用法
1. 主鍵約束(PRIMARY KEY)
-
作用:唯一標(biāo)識(shí)每行數(shù)據(jù),不允許重復(fù)或
NULL。 -
語(yǔ)法:
CREATE TABLE 表名 ( 列1 數(shù)據(jù)類型, 列2 數(shù)據(jù)類型, CONSTRAINT 約束名 PRIMARY KEY (列1, 列2) -- 復(fù)合主鍵 ); -
示例:
CREATE TABLE students ( student_id INT, course_id INT, grade DECIMAL(5,2), CONSTRAINT pk_student_course PRIMARY KEY (student_id, course_id) -- 復(fù)合主鍵 );
2. 外鍵約束(FOREIGN KEY)
- 作用:確保兩表之間的數(shù)據(jù)關(guān)聯(lián)有效。
-
語(yǔ)法:
CREATE TABLE 表名 ( 列1 數(shù)據(jù)類型, 列2 數(shù)據(jù)類型, CONSTRAINT 約束名 FOREIGN KEY (外鍵列) REFERENCES 主表名 (主表列) ON DELETE 級(jí)聯(lián)操作 ON UPDATE 級(jí)聯(lián)操作 ); -
示例:
CREATE TABLE orders ( order_id INT PRIMARY KEY, user_id INT, CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE -- 主表刪除時(shí),級(jí)聯(lián)刪除從表數(shù)據(jù) ON UPDATE SET NULL -- 主表更新時(shí),從表外鍵設(shè)為 NULL );
3. 唯一約束(UNIQUE)
-
作用:確保某列(或列組合)的值唯一,允許
NULL。 -
語(yǔ)法:
CREATE TABLE 表名 ( 列1 數(shù)據(jù)類型, 列2 數(shù)據(jù)類型, CONSTRAINT 約束名 UNIQUE (列1, 列2) -- 復(fù)合唯一約束 ); -
示例:
CREATE TABLE employees ( emp_id INT PRIMARY KEY, email VARCHAR(100), CONSTRAINT uc_email UNIQUE (email) -- 確保郵箱唯一 );
4. 檢查約束(CHECK)
- 作用:限制列值必須滿足條件(MySQL 8.0+ 支持)。
-
語(yǔ)法:
CREATE TABLE 表名 ( 列1 數(shù)據(jù)類型, 列2 數(shù)據(jù)類型, CONSTRAINT 約束名 CHECK (條件) ); -
示例:
CREATE TABLE products ( product_id INT PRIMARY KEY, price DECIMAL(10,2), CONSTRAINT chk_price CHECK (price > 0) -- 價(jià)格必須大于 0 );
5. 默認(rèn)值(DEFAULT)
- 作用:插入數(shù)據(jù)時(shí),未指定列值時(shí)使用默認(rèn)值。
-
語(yǔ)法:
CREATE TABLE 表名 ( 列1 數(shù)據(jù)類型 DEFAULT 默認(rèn)值 ); -
示例:
CREATE TABLE orders ( order_date DATE DEFAULT CURRENT_DATE -- 默認(rèn)當(dāng)前日期 );
三、CONSTRAINT 的管理操作
1. 添加約束
-
添加主鍵:
ALTER TABLE students ADD CONSTRAINT pk_student PRIMARY KEY (student_id); -
添加外鍵:
ALTER TABLE orders ADD CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users(user_id);
2. 刪除約束
-
刪除主鍵:
ALTER TABLE students DROP PRIMARY KEY; -- 主鍵無(wú)需指定名稱 -
刪除外鍵:
ALTER TABLE orders DROP FOREIGN KEY fk_user; -- 需指定外鍵名稱
四、實(shí)際應(yīng)用場(chǎng)景
場(chǎng)景 1:防止重復(fù)數(shù)據(jù)
-- 確保書名和作者組合唯一
CREATE TABLE books (
isbn VARCHAR(13) PRIMARY KEY,
title VARCHAR(100),
author VARCHAR(50),
CONSTRAINT uc_title_author
UNIQUE (title, author)
);
場(chǎng)景 2:級(jí)聯(lián)刪除關(guān)聯(lián)數(shù)據(jù)
-- 刪除用戶時(shí),自動(dòng)刪除其訂單
CREATE TABLE orders (
order_id INT PRIMARY KEY,
user_id INT,
CONSTRAINT fk_user
FOREIGN KEY (user_id)
REFERENCES users(user_id)
ON DELETE CASCADE
);
場(chǎng)景 3:強(qiáng)制業(yè)務(wù)規(guī)則
-- 確保員工年齡 ≥ 18 歲
CREATE TABLE employees (
emp_id INT PRIMARY KEY,
age INT,
CONSTRAINT chk_age
CHECK (age >= 18)
);
五、注意事項(xiàng)
-
命名規(guī)范:使用
pk_表名、fk_表名_列名等格式,增強(qiáng)可讀性。 - 存儲(chǔ)引擎:外鍵約束需使用 InnoDB,MyISAM 不支持。
- 性能影響:過(guò)多的約束可能降低寫入性能。
-
版本兼容性:
CHECK約束僅 MySQL 8.0+ 完全支持。
六、完整示例
-- 主表:部門
CREATE TABLE departments (
dept_id INT PRIMARY KEY,
dept_name VARCHAR(50) NOT NULL UNIQUE
);
-- 從表:?jiǎn)T工(含外鍵和檢查約束)
CREATE TABLE employees (
emp_id INT PRIMARY KEY,
emp_name VARCHAR(50) NOT NULL,
dept_id INT,
salary DECIMAL(10,2),
CONSTRAINT fk_dept
FOREIGN KEY (dept_id)
REFERENCES departments(dept_id)
ON DELETE SET NULL,
CONSTRAINT chk_salary
CHECK (salary >= 3000)
);
通過(guò)合理使用 CONSTRAINT,可以顯著提升數(shù)據(jù)的準(zhǔn)確性和一致性,是數(shù)據(jù)庫(kù)設(shè)計(jì)的核心技能之一。
以下是 15道關(guān)于 MySQL CONSTRAINT 的練習(xí)題,涵蓋主鍵、外鍵、唯一約束、檢查約束等核心用法,幫助你鞏固知識(shí)并熟練使用約束規(guī)則:
基礎(chǔ)練習(xí)(1-5)
-
創(chuàng)建表時(shí)定義主鍵約束
創(chuàng)建一個(gè)students表,包含student_id(主鍵)、name、age,并為student_id顯式命名主鍵約束為pk_student。
CREATE TABLE students (
student_id INT,
name VARCHAR(50),
age INT,
CONSTRAINT pk_student PRIMARY KEY (student_id)
);
添加復(fù)合主鍵約束
創(chuàng)建一個(gè)course_selection表,包含student_id和course_id,要求二者的組合為主鍵,約束命名為pk_student_course。定義唯一約束
在employees表中,為email列添加唯一約束,命名為uc_email,確保郵箱唯一。創(chuàng)建外鍵約束
在orders表中添加user_id列,并創(chuàng)建外鍵約束fk_user,使其引用users表的user_id列,級(jí)聯(lián)刪除從表數(shù)據(jù)。檢查約束限制數(shù)值范圍
創(chuàng)建一個(gè)products表,包含price列,要求價(jià)格必須大于 0,約束命名為chk_price。
進(jìn)階練習(xí)(6-10)
多列唯一約束
在books表中,為title和author列添加唯一約束uc_title_author,確保書名和作者組合唯一。級(jí)聯(lián)更新外鍵
修改orders表的外鍵約束fk_user,使其在主表users的user_id更新時(shí),從表的user_id自動(dòng)更新。刪除主鍵約束
刪除students表的主鍵約束pk_student,然后重新添加一個(gè)新的主鍵約束到student_id列。檢查約束限制日期
在events表中,添加約束chk_event_date,確保start_date必須早于end_date。默認(rèn)值約束
在orders表中,為order_date列設(shè)置默認(rèn)值為當(dāng)前日期,約束命名為df_order_date。
實(shí)戰(zhàn)場(chǎng)景(11-15)
復(fù)合外鍵約束
創(chuàng)建一個(gè)order_details表,包含order_id和product_id,并添加外鍵約束fk_order_product,使其同時(shí)引用orders表的order_id和products表的product_id。檢查約束限制年齡
在users表中,添加約束chk_age,確保age列的值在 18 到 100 之間。刪除外鍵約束
從orders表中刪除外鍵約束fk_user,然后重新添加一個(gè)允許主表更新時(shí)從表設(shè)為NULL的外鍵約束。自增主鍵約束
在employees表中,定義emp_id為自增主鍵,約束命名為pk_emp。檢查約束限制字符串格式
在users表中,添加約束chk_phone,確保phone列為 11 位數(shù)字(模擬手機(jī)號(hào)格式)。
附加挑戰(zhàn)
-
場(chǎng)景 1:在
employees表中,添加約束chk_salary,確保salary必須大于等于3000,且department_id必須存在于departments表中。 -
場(chǎng)景 2:創(chuàng)建一個(gè)
projects表,包含project_id(主鍵)、start_date、end_date,并添加約束確保end_date必須比start_date晚至少 7 天。
練習(xí)要求
- 每個(gè)練習(xí)需寫出完整的 SQL 語(yǔ)句。
- 顯式命名所有約束(如
pk_xxx、fk_xxx)。 - 驗(yàn)證約束效果(如嘗試插入違反約束的數(shù)據(jù),觀察是否報(bào)錯(cuò))。
通過(guò)完成這些練習(xí),你將熟練掌握 CONSTRAINT 的核心用法,并能在實(shí)際項(xiàng)目中靈活應(yīng)用約束規(guī)則!
基礎(chǔ)練習(xí)答案
1. 創(chuàng)建表時(shí)定義主鍵約束
2. 添加復(fù)合主鍵約束
CREATE TABLE course_selection (
student_id INT,
course_id INT,
grade DECIMAL(5,2),
CONSTRAINT pk_student_course PRIMARY KEY (student_id, course_id)
);
3. 定義唯一約束
CREATE TABLE employees (
emp_id INT PRIMARY KEY,
email VARCHAR(100),
CONSTRAINT uc_email UNIQUE (email)
);
4. 創(chuàng)建外鍵約束(級(jí)聯(lián)刪除)
CREATE TABLE orders (
order_id INT PRIMARY KEY,
user_id INT,
CONSTRAINT fk_user
FOREIGN KEY (user_id)
REFERENCES users(user_id)
ON DELETE CASCADE
);
5. 檢查約束限制數(shù)值范圍
CREATE TABLE products (
product_id INT PRIMARY KEY,
price DECIMAL(10,2),
CONSTRAINT chk_price CHECK (price > 0)
);
進(jìn)階練習(xí)答案
6. 多列唯一約束
CREATE TABLE books (
book_id INT PRIMARY KEY,
title VARCHAR(100),
author VARCHAR(50),
CONSTRAINT uc_title_author UNIQUE (title, author)
);
7. 級(jí)聯(lián)更新外鍵
ALTER TABLE orders
ADD CONSTRAINT fk_user
FOREIGN KEY (user_id)
REFERENCES users(user_id)
ON DELETE CASCADE
ON UPDATE CASCADE; -- 級(jí)聯(lián)更新
8. 刪除并重新添加主鍵約束
-- 刪除主鍵
ALTER TABLE students DROP PRIMARY KEY;
-- 重新添加主鍵
ALTER TABLE students
ADD CONSTRAINT pk_student_new PRIMARY KEY (student_id);
9. 檢查約束限制日期范圍
CREATE TABLE events (
event_id INT PRIMARY KEY,
start_date DATE,
end_date DATE,
CONSTRAINT chk_event_date CHECK (start_date < end_date)
);
10. 默認(rèn)值約束
CREATE TABLE orders (
order_id INT PRIMARY KEY,
order_date DATE DEFAULT (CURRENT_DATE)
);
實(shí)戰(zhàn)場(chǎng)景答案
11. 復(fù)合外鍵約束
CREATE TABLE order_details (
order_id INT,
product_id INT,
quantity INT,
CONSTRAINT fk_order_product
FOREIGN KEY (order_id, product_id)
REFERENCES orders(order_id, product_id) -- 假設(shè) orders 和 products 有復(fù)合主鍵
);
12. 檢查約束限制年齡范圍
CREATE TABLE users (
user_id INT PRIMARY KEY,
age INT,
CONSTRAINT chk_age CHECK (age BETWEEN 18 AND 100)
);
13. 刪除并重新添加外鍵約束
-- 刪除外鍵
ALTER TABLE orders DROP FOREIGN KEY fk_user;
-- 重新添加外鍵(允許更新時(shí)設(shè)為 NULL)
ALTER TABLE orders
ADD CONSTRAINT fk_user_new
FOREIGN KEY (user_id)
REFERENCES users(user_id)
ON DELETE SET NULL
ON UPDATE SET NULL;
14. 自增主鍵約束
CREATE TABLE employees (
emp_id INT AUTO_INCREMENT PRIMARY KEY,
emp_name VARCHAR(50),
CONSTRAINT pk_emp PRIMARY KEY (emp_id)
);
15. 檢查約束限制手機(jī)號(hào)格式
CREATE TABLE users (
user_id INT PRIMARY KEY,
phone VARCHAR(11),
CONSTRAINT chk_phone CHECK (phone REGEXP '^[0-9]{11}$')
);
附加挑戰(zhàn)答案
挑戰(zhàn) 1:檢查薪資與部門關(guān)聯(lián)
CREATE TABLE employees (
emp_id INT PRIMARY KEY,
salary DECIMAL(10,2),
department_id INT,
CONSTRAINT chk_salary CHECK (salary >= 3000),
CONSTRAINT fk_dept
FOREIGN KEY (department_id)
REFERENCES departments(dept_id)
);
挑戰(zhàn) 2:檢查項(xiàng)目日期間隔
CREATE TABLE projects (
project_id INT PRIMARY KEY,
start_date DATE,
end_date DATE,
CONSTRAINT chk_project_dates
CHECK (DATEDIFF(end_date, start_date) >= 7)
);
驗(yàn)證方法
-
插入合法數(shù)據(jù):
INSERT INTO products (product_id, price) VALUES (1, 10.5); -- 成功 -
插入非法數(shù)據(jù):
INSERT INTO products (product_id, price) VALUES (2, -5); -- 失敗,違反 chk_price -
查看約束信息:
SHOW CREATE TABLE products; -- 顯示所有約束定義
通過(guò)以上練習(xí),你可以熟練掌握 CONSTRAINT 的用法,并能在實(shí)際項(xiàng)目中靈活應(yīng)用!