SQL 约束(建议收藏)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观
在数据库设计中,"SQL 约束" 是确保数据完整性和一致性的重要工具。无论是开发简单的学生信息管理系统,还是复杂的电商平台,合理使用约束都能避免数据混乱,提升系统可靠性。本文将通过生活化的比喻和实际案例,系统讲解 SQL 约束的核心概念与应用场景,帮助读者快速掌握这一关键技能。
主键约束(Primary Key)
定义与作用
主键约束是数据库中唯一标识一条记录的"身份证"。它确保每条记录的主键值既不重复也不为空,如同每个人都有唯一的身份证号码。例如,在用户表中,user_id
通常被设为主键,避免出现两个用户拥有相同的唯一标识。
代码示例
CREATE TABLE users (
user_id INT PRIMARY KEY,
username VARCHAR(50),
email VARCHAR(100)
);
如果尝试插入两条 user_id
为 1 的记录,数据库会直接报错:
INSERT INTO users (user_id, username)
VALUES (1, 'Alice'), (1, 'Bob');
-- Error: Duplicate entry '1' for key 'PRIMARY'
实际应用
主键的设计需考虑业务场景。例如电商平台的商品表,若商品编码有唯一性且永不重复,可直接设为 product_id
主键;若需自动生成唯一值,可使用自增字段:
CREATE TABLE products (
product_id INT AUTO_INCREMENT PRIMARY KEY,
product_name VARCHAR(255)
);
外键约束(Foreign Key)
数据关联的"纽带"
外键约束用于建立表与表之间的关系,确保引用完整性。假设有一个订单表 orders
需关联用户表 users
,外键 user_id
必须存在于 users
表的 user_id
列中。这就像家庭成员之间的关系:孩子必须属于某个家庭,不能凭空存在。
创建与验证
CREATE TABLE orders (
order_id INT PRIMARY KEY,
user_id INT,
FOREIGN KEY (user_id) REFERENCES users(user_id)
);
若尝试插入一个 user_id
不存在的订单:
INSERT INTO orders (order_id, user_id)
VALUES (1001, 999); -- 假设 users 表中没有 user_id=999
-- Error: Cannot add or update a child row
级联操作
外键可配合 ON DELETE
和 ON UPDATE
实现级联操作:
ALTER TABLE orders
ADD CONSTRAINT fk_user
FOREIGN KEY (user_id)
REFERENCES users(user_id)
ON DELETE CASCADE
ON UPDATE CASCADE;
当删除用户时,其关联订单会自动删除,避免数据残留。
唯一约束(Unique Constraint)
避免重复的"过滤网"
唯一约束确保某一列(或组合列)的值不重复,但允许 NULL
值。例如,用户表中的邮箱地址需要唯一性,防止重复注册:
CREATE TABLE users (
user_id INT PRIMARY KEY,
email VARCHAR(100) UNIQUE
);
若尝试插入相同邮箱:
INSERT INTO users (user_id, email)
VALUES (2, 'alice@example.com'), (3, 'alice@example.com');
-- Error: Duplicate entry 'alice@example.com' for key 'email_UNIQUE'
组合唯一约束
多个字段的组合也可设为唯一,例如课程表中的 course_code
和 semester
组合需唯一:
CREATE TABLE courses (
course_id INT PRIMARY KEY,
course_code VARCHAR(10),
semester VARCHAR(20),
UNIQUE (course_code, semester)
);
非空约束(NOT NULL)
数据完整性"守护者"
非空约束强制字段必须包含值,避免关键信息缺失。例如,用户表的 username
和 email
不应为空:
CREATE TABLE users (
user_id INT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL
);
尝试插入缺少 username
的记录会失败:
INSERT INTO users (user_id, email)
VALUES (4, 'bob@example.com');
-- Error: Field 'username' doesn't have a default value
与默认值的结合
若字段需要非空但允许默认值,可结合 DEFAULT
约束:
CREATE TABLE posts (
post_id INT PRIMARY KEY,
content TEXT NOT NULL,
status VARCHAR(10) NOT NULL DEFAULT 'draft'
);
检查约束(CHECK Constraint)
数据范围的"守门人"
检查约束通过逻辑条件限制列的取值范围。例如,年龄字段需在 18-100 岁之间:
CREATE TABLE users (
user_id INT PRIMARY KEY,
age INT CHECK (age BETWEEN 18 AND 100)
);
插入 age=17
的记录会报错:
INSERT INTO users (user_id, age)
VALUES (5, 17);
-- Error: Check constraint 'age' is violated.
跨字段验证
部分数据库(如 PostgreSQL)支持跨列条件:
CREATE TABLE products (
product_id INT PRIMARY KEY,
price DECIMAL(10,2),
discount DECIMAL(5,2),
CHECK (discount <= price)
);
默认约束(DEFAULT Constraint)
自动填充的"智能助手"
默认约束为字段指定默认值,简化数据录入。例如,订单表的 created_at
可自动设为当前时间:
CREATE TABLE orders (
order_id INT PRIMARY KEY,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
插入记录时无需手动填写时间:
INSERT INTO orders (order_id)
VALUES (1002);
-- created_at 自动设为插入时的时间
结合业务逻辑
默认值可配合其他约束使用,例如用户状态默认为 "active":
CREATE TABLE users (
user_id INT PRIMARY KEY,
status VARCHAR(10) DEFAULT 'active' NOT NULL
);
约束的添加与修改
动态调整约束
已存在的表可通过 ALTER TABLE
添加约束:
-- 添加非空约束
ALTER TABLE users
MODIFY COLUMN email VARCHAR(100) NOT NULL;
-- 添加外键约束
ALTER TABLE orders
ADD CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users(user_id);
删除约束
ALTER TABLE orders
DROP FOREIGN KEY fk_user;
实战案例:设计学生选课系统
表结构设计
CREATE TABLE students (
student_id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE
);
CREATE TABLE courses (
course_id INT PRIMARY KEY,
course_code VARCHAR(10) NOT NULL,
credits INT CHECK (credits BETWEEN 1 AND 6)
);
CREATE TABLE enrollments (
enrollment_id INT PRIMARY KEY,
student_id INT,
course_id INT,
grade CHAR(2),
FOREIGN KEY (student_id) REFERENCES students(student_id),
FOREIGN KEY (course_id) REFERENCES courses(course_id),
UNIQUE (student_id, course_id) -- 同一学生不可重复选同一课程
);
数据验证示例
尝试插入无效数据时:
INSERT INTO courses (course_id, course_code, credits)
VALUES (101, 'MATH101', 7);
-- Error: Check constraint 'credits' is violated.
结论
通过合理运用 SQL 约束,开发者可以构建出更健壮、可靠的数据库系统。从主键的唯一标识,到外键的关联验证,再到检查约束的数据范围控制,每种约束都在保障数据的"纯净性"。建议在设计初期就规划好约束策略,并通过实际案例反复验证。随着项目复杂度的提升,这些约束将成为维护数据质量的坚实屏障。
掌握 SQL 约束不仅需要理论理解,更需通过动手实践加深记忆。尝试为现有项目添加约束,观察数据行为的变化,逐步培养数据库设计的"约束思维"。记住,良好的约束设计如同为数据穿上"防护衣",让系统在应对海量操作时依然稳定如初。