1. 遵循三大范式(Normalization)
范式是关系型数据库设计的规范,目的是减少数据冗余和异常。
1.1 第一范式(1NF):原子性
要求字段值具有原子性,不可再分。
反例:在"联系方式"字段中存储"电话:123-邮箱:abc@xx.com"(可拆分为两个字段)
正例:拆分为"电话"和"邮箱"两个独立字段
1.2 第二范式(2NF):消除部分依赖
在1NF基础上,非主键字段必须完全依赖于主键(不能只依赖主键的一部分)。
反例:订单表(订单ID, 产品ID, 产品名称, 订单日期)
问题:"产品名称"只依赖"产品ID"(主键是订单ID+产品ID)
正例:拆分为订单表(订单ID, 产品ID, 订单日期)和产品表(产品ID, 产品名称)
1.3 第三范式(3NF):消除传递依赖
在2NF基础上,非主键字段不能依赖于其他非主键字段(即不传递依赖)。
反例:用户表(用户ID, 姓名, 部门ID, 部门名称)
问题:"部门名称"依赖"部门ID",而非直接依赖主键"用户ID"
正例:拆分为用户表(用户ID, 姓名, 部门ID)和部门表(部门ID, 部门名称)
提示:范式并非越高越好,实际设计中可适当反范式化(如增加冗余字段)提升查询效率。
2. 主键与外键设计原则
2.1 主键(Primary Key)
- 每个表应有唯一主键,用于唯一标识一条记录
- 推荐使用无业务含义的自增ID或UUID(避免用手机号、身份证等可变化的业务字段)
- 主键应简洁(如int类型比字符串更高效)
2.2 外键(Foreign Key)
- 用于关联两个表,指向另一表的主键
- 通过外键约束保证数据一致性(如删除主表记录时,子表关联记录需处理:级联删除/置空/报错)
- 命名建议:用"关联表名_主键名",如"user_id"、"order_id"
用户表(users): id (主键), name, age
订单表(orders): id (主键), user_id (外键,关联users.id), amount
3. 避免数据冗余
冗余数据指重复存储的信息,会导致更新异常(修改一处时需同步修改多处)。
反例:在"订单表"和"订单详情表"中都存储"客户姓名"
优化:只在"客户表"存储一次,其他表通过客户ID关联查询
例外:在高并发场景下,可故意保留少量冗余(如商品列表中的"分类名称"),以减少关联查询,提升性能。
5. 表与关系设计
表之间的关系主要有三种:
5.1 一对一(1:1)
两个表的记录一一对应(如"用户表"和"用户详情表")。
解决方案:在其中一个表添加外键,关联另一表的主键,并设置外键唯一(UNIQUE)。
5.2 一对多(1:N)
一个表的记录对应另一表的多条记录(如"用户表"和"订单表")。
解决方案:在"多"的一方添加外键,关联"一"的一方的主键(如订单表添加user_id)。
5.3 多对多(M:N)
两个表的记录相互对应多条(如"学生表"和"课程表")。
解决方案:创建中间表,存储两个表的主键作为联合主键(如"学生课程表"含student_id和course_id)。