MySQL数据库约束全解析:主键、外键、唯一、非空...一篇搞定!
(基于MYSQL8.0以上版本)
本文适合MySQL初学者、需要巩固基础概念的开发者,以及所有关注数据完整性的数据库使用者。约束是数据库的守护者,它能防止垃圾数据、保证关联正确性,让您的数据始终保持干净可靠!
一、什么是数据库约束?
约束是强加于数据列的规则,用于:
✅ 防止无效数据插入(如空值、重复值)✅ 维护表间关系完整性(如订单必须关联有效用户)✅ 自动执行数据规则(如年龄不能为负数)
-- 典型约束示例
CREATE TABLE users (
id INT PRIMARY KEY, -- 主键约束
email VARCHAR(50) UNIQUE NOT NULL, -- 唯一+非空
age INT CHECK (age >= 18) -- 检查约束
);
二、六大核心约束详解(含实战代码)
1. 主键约束 (PRIMARY KEY)
作用:唯一标识每行记录,相当于数据的"身份证号",不可为空且唯一
CREATE TABLE employees (
emp_id INT PRIMARY KEY, -- 单列主键
name VARCHAR(50)
);
-- 复合主键
CREATE TABLE order_details (
order_id INT,
product_id INT,
PRIMARY KEY (order_id, product_id)
);
常见错误:
INSERT INTO employees VALUES (1, '张三'); -- 成功
INSERT INTO employees VALUES (1, '李四'); -- 报错:Duplicate entry '1'
INSERT INTO employees VALUES (NULL, '王五'); -- 报错:Column 'emp_id' cannot be null
2. 外键约束 (FOREIGN KEY)
作用:强制表间引用完整性
CREATE TABLE orders (
order_id INT PRIMARY KEY,
user_id INT,
FOREIGN KEY (user_id) REFERENCES users(id)
);
错误演示:
-- 父表无id=100时插入子表
INSERT INTO orders VALUES (1, 100);
-- 报错:Cannot add or update a child row: a foreign key constraint fails
3. 唯一约束 (UNIQUE)
作用:确保列值唯一(允许NULL)
CREATE TABLE products (
product_id INT PRIMARY KEY,
sku_code VARCHAR(20) UNIQUE -- 唯一约束
);
与主键区别:
特性主键唯一约束NULL值❌ 不允许✅ 允许数量限制每表仅1个可多个索引类型聚集索引非聚集索引
错误测试:
INSERT INTO products VALUES (1, 'A100'); -- 成功
INSERT INTO products VALUES (2, 'A100'); -- 报错:Duplicate entry 'A100'
INSERT INTO products VALUES (3, NULL); -- 成功(NULL不触发唯一性)
4. 非空约束 (NOT NULL)
作用:强制列不允许NULL值
CREATE TABLE customers (
cust_id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL, -- 非空约束
phone VARCHAR(20)
);
错误案例:
INSERT INTO customers (cust_id, phone)
VALUES (1, '13800138000'); -- 报错:Field 'name' doesn't have a default value
5. 默认值约束 (DEFAULT)
作用:未指定值时自动填充默认值
CREATE TABLE logs (
log_id INT PRIMARY KEY,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 默认当前时间
);
使用场景:
INSERT INTO logs (log_id) VALUES (1); -- created_at自动填充
6. 检查约束 (CHECK) - MySQL 8.0+重点
作用:自定义数据验证规则
CREATE TABLE students (
student_id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
age INT CHECK (age BETWEEN 6 AND 60), -- 年龄范围检查
gender CHAR(1) CHECK (gender IN ('M','F'))
);
错误触发:
INSERT INTO students VALUES (1, '小明', 5, 'M');
-- 报错:Check constraint 'students_chk_1' is violated
三、综合应用:博客系统实战
-- 用户表(主表)
CREATE TABLE users (
user_id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(30) UNIQUE NOT NULL,
email VARCHAR(50) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 文章表(外键关联)
CREATE TABLE articles (
article_id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(100) NOT NULL,
content TEXT NOT NULL,
user_id INT NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(user_id)
);
-- 评论表(双重外键)
CREATE TABLE comments (
comment_id INT AUTO_INCREMENT PRIMARY KEY,
content TEXT NOT NULL,
user_id INT NOT NULL,
article_id INT NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(user_id),
FOREIGN KEY (article_id) REFERENCES articles(article_id)
);
四、避坑指南与最佳实践
约束命名规范
CONSTRAINT fk_orders_users FOREIGN KEY (user_id) REFERENCES users(id)
命名后可通过ALTER TABLE orders DROP FOREIGN KEY fk_orders_users;精准删除
五、总结
约束类型核心作用关键要点主键唯一标识不允许NULL,每表仅一个外键跨表引用完整性注意ON DELETE规则选择唯一禁止重复值允许NULL,可多列设置非空强制字段必有值与DEFAULT配合使用默认值自动填充空字段减少业务逻辑代码检查自定义数据规则MySQL 8.0+原生支持
📌 最后忠告:约束是数据库设计的安全护栏,初期投入几分钟的约束设计,可避免未来数小时的数据清洗!
欢迎在评论区留言讨论:您在项目中遇到过哪些约束引发的"坑"?或者有更好的实践建议?
#MySQL #数据库约束 #数据完整性 #外键 #主键 #数据库设计