

新闻资讯
技术学院实体是业务中真实存在的对象,需拆分为符合范式的表;外键必须用InnoDB引擎并严格匹配类型;一对多外键置于“多”方,多对多必用联合主键中间表。
“学生”“班级”“订单”这些不是数据库概念,而是你业务里真实存在的东西——它们就是实体。MySQL 里没有 ENTITY 关键字,所谓“实体”最终必须落地为一张张表。一张表对应一个实体集(比如所有学生的集合),一行记录对应一个具体实体
(比如张三这个学生),一列字段对应该实体的一个属性(比如 stu_name、age)。
常见误区是把“一份 Excel 表格”直接当实体建表:比如把「学生+班级+任课老师+成绩」全塞进一张 student_all_info 表。这看似方便,实则违反第一范式(字段可再分)、第二范式(部分依赖)、第三范式(传递依赖),后续改字段、查数据、加索引都会踩坑。
students 和 classes 两张表student_courses,不能在任一主表里硬加逗号分隔的课程 ID 字符串students_profile 表,用相同 stu_id 主键关联,而非堆在主表里拖慢常用查询外键(FOREIGN KEY)不是为了画 ER 图好看,而是让 MySQL 帮你守住数据一致性底线。它强制子表中每条记录的外键值,必须存在于父表的主键中;删除/更新父表记录时,还能自动级联或置空子表关联项。
但很多人建了外键却没生效——原因通常是:ENGINE=MyISAM 不支持外键(必须用 InnoDB),或建表时漏写 CONSTRAINT 名称导致无法管理,或外键字段类型与父表主键不严格一致(比如一个是 INT,另一个是 SMALLINT)。
CREATE TABLE students (
stu_id INT PRIMARY KEY,
class_id INT NOT NULL,
stu_name VARCHAR(20),
FOREIGN KEY (class_id) REFERENCES classes(class_id)
ON DELETE CASCADE
ON UPDATE CASCADE
) ENGINE=InnoDB;
ENGINE=InnoDB,否则外键语句被静默忽略class_id 在子表和父表中类型、符号(SIGNED/UNSIGNED)、长度需完全一致ON DELETE CASCADE 要慎用:删一个班级,所有学生记录也被删,业务上可能不合理;更安全的是 ON DELETE SET NULL(前提是字段允许 NULL)班级 → 学生 是典型一对多。设计错误常出现在“把外键加在班级表里”,比如给 classes 表加个 student_ids 字段存 “1,5,8” —— 这彻底放弃关系型数据库能力,变成字符串解析游戏,无法索引、无法 JOIN、无法保证原子性。
正确做法永远只有一条:外键字段放在“多”的一方,即 students 表里加 class_id,并指向 classes.class_id。这样一条学生记录只属于一个班级,而一个班级 ID 可在学生表中出现多次。
CREATE INDEX idx_class_id ON students(class_id);
student_classes(stu_id, class_id)
老师 ↔ 班级、用户 ↔ 权限、商品 ↔ 标签……这类关系绝不能用字段拼接、JSON 字符串或双外键字段硬塞进主表。唯一合规解法是新建一张中间表,每行代表一个有效关联。
中间表通常以两个外键组成联合主键,既避免重复关系(如老师 A 已教班级 B,再插一次会被主键冲突拦截),又天然支持高效双向查询。
CREATE TABLE teacher_classes ( teacher_id INT NOT NULL, class_id INT NOT NULL, PRIMARY KEY (teacher_id, class_id), FOREIGN KEY (teacher_id) REFERENCES teachers(teacher_id) ON DELETE CASCADE, FOREIGN KEY (class_id) REFERENCES classes(class_id) ON DELETE CASCADE ) ENGINE=InnoDB;
id 主键——它不表达业务含义,还浪费空间和索引开销(teacher_id, class_id),但若常查“某班级有哪些老师”,需额外建 INDEX idx_class_id ON teacher_classes(class_id)
user_roles),清晰表明其桥梁性质class_teachers 里,而不是强行塞进任一主表。