MySQL不支持表继承,因其关系型设计专注OLTP性能而非OOP建模;替代方案有单一表、类表和EAV模式,其中类表模式需注意主键复用、类型排他性及JOIN安全。MySQL 本身不支持表继承,也没有原生的面向对象建模能力。你不能像在 Java 或 Python 中那样写
class Employee extends Person,然后期望 MySQL 自动处理字段复用、多态查询或父类约束。
这本质是个建模层与存储层错位的问题:应用逻辑想用 OOP 思维组织数据,但 MySQL 是关系型引擎,只认表、列、外键和索引。
MySQL 解析器根本不识别 INHERITS、EXTENDS TABLE 这类关键字(PostgreSQL 有有限的 INHERITS,但 MySQL 完全没有)。任何试图执行类似语句的操作都会报错:
ERROR 1064 (42000): You have an error in your SQL syntax。这不是版本问题,是设计取舍——MySQL 专注 OLTP 场景下的稳定与性能,而非抽象建模能力。
实际项目中,有三种主流做法,选哪个取决于你的查询模式、变更频率和一致性要求:
type 字段区分角色。适合子类差异小、查询常跨类型(如“查所有活跃用户,不管是不是管理员”),但空字段多、schema 膨胀快。users),每个子类一张扩展表(如 admins、customers),通过 user_id 外键关联。适合子类字段多、业务逻辑隔离强,但 JOIN 查询频繁,且无法强制某条记录“只能属于一个子类”。entity_id, attr_key, attr_value)。灵活性高,但几乎放弃 SQL 查询能力、索引失效、难以校验类型,仅适用于配置类极低频读写的场景,不推荐用于核心业务实体。如果选类表模式(最接近“继承语义”的折中方案),这些点容易踩坑:
CREATE TABLE users ( id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100), email VARCHAR(255) ); CREATE TABLE admins ( i否则无法保证一对一绑定,也难以做级联删除。d BIGINT PRIMARY KEY, role_level TINYINT, FOREIGN KEY (id) REFERENCES users(id) ON DELETE CASCADE );
admins 和 customers 表中存在”),得靠应用逻辑或触发器(但触发器在分布式写入下不可靠)。LEFT JOIN 比 INNER JOIN 更安全——避免因漏插子表数据导致整条记录消失;但要注意 NULL 值处理逻辑是否符合业务预期。Django ORM、SQLAlchemy、MyBatis Plus 等框架提供的“继承映射”只是语法糖,底层仍是上述某一种物理模型。比如 Django 的 abstract = True 只影响迁移生成,不改变数据库结构;而 multi-table inheritance 就对应类表模式,并自动生成 JOIN 查询。关键点在于:别让 ORM 掩盖了底层 JOIN 成本和约束缺失的事实。一旦需要写原生 SQL 或做性能调优,你得立刻切回真实表结构去思考。