mysql菜鸟教程
10.2 第一范式(1NF)
在数据库规范化中,第一范式(1NF,First Normal Form) 是最基本的要求。一个表如果满足第一范式,意味着它已经具备了关系数据库的基本特征。几乎所有关系数据库管理系统(RDBMS)创建的表天然就是1NF的,因为关系模型本身就要求每个属性都是原子的。但为了理解规范化的原理,我们还是需要明确第一范式的定义和规则。
一、第一范式的核心要求
第一范式要求表中的每一列都是不可再分的原子值,且每一行是唯一确定的。
具体来说,1NF 包含以下几条规则:
每一列都必须是原子的(atomic):即列中存储的值不能再被拆分成更小的独立部分。例如,一个“地址”列如果包含了省、市、区、街道的全部信息,就不是原子的。
每一列只能存储一个值:不允许一个单元格内包含多个值(如用逗号分隔的列表)。
不能有重复的组(repeating groups):即表中不能出现多个列用于存储同一类信息的多个值(如 phone1, phone2, phone3 这样的设计)。
必须有主键:表中的每一行必须能够被唯一标识。虽然主键并不是1NF的强制要求,但它是关系表的基础,没有主键就无法保证行的唯一性。
二、不符合1NF的典型例子
1. 非原子值:一个单元格包含多个数据
假设我们有一张 students 表,其中有一列存储学生的联系电话,但有些学生有多个电话,我们可能会这样设计:
这里的 phones 列存储了多个电话号码(用逗号分隔),违反了1NF的原子性要求。这会导致查询困难:比如要查找拥有某个电话号码的学生,需要使用字符串匹配函数,效率低下且容易出错。
2. 重复组:用多列存储同类数据
另一种常见反模式是用多个列存储同一类信息,例如为学生存储多个联系电话:
这种设计虽然将每个电话存到了单独的列,但引入了新的问题:
最多只能存储固定数量的电话(如3个),如果某个学生有4个电话就无法存储。
查询需要判断哪个列有值,增加了复杂度。
统计所有电话号码时需要多个列联合查询。
这也违反了1NF,因为存在重复组(repeating groups),实际上是将同一个属性(电话号码)拆分成了多个列。
3. 缺乏主键
如果一张表没有定义主键,或者存在完全相同的两行,就无法唯一标识记录,这也不符合关系模型的基本要求,当然也不满足1NF(虽然1NF本身没有明确要求主键,但通常认为它是必需的)。
三、如何转换为1NF
要解决上述问题,我们需要将表拆分成多个表,或者将非原子列拆分成多行。
针对非原子列(一个单元格多个值)
对于 students 表,我们可以将电话号码单独存放到另一张表 student_phones 中,与原表建立一对多关系:
students 表:
student_phones 表:
现在每一列都是原子的,每一行只存储一个电话,并且通过 student_id 关联回原表。这完全满足1NF,并且扩展性更好,无论学生有多少电话都可以存储。
针对重复组(多列存储同类数据)
对于重复组的例子,同样可以拆分成两张表,方法与上面相同。
针对缺乏主键的表
只需为表添加一个主键列即可,例如自增的 id 列。
四、第一范式的意义
满足第一范式是进入关系数据库世界的门槛。它强制我们将数据组织成“扁平的”二维表,每一行代表一个实体或一个关系,每一列代表一个单一的属性。这为后续的规范化(2NF、3NF)奠定了基础,也使SQL查询能够以标准、高效的方式执行。
五、需要注意的细节
原子性是一个相对概念:什么算是“原子”取决于业务需求。例如,一个“地址”字段在有些应用中需要拆分成省、市、区、街道,因为需要按地区统计;但在另一些应用中,可能只需要一个完整的地址字符串即可。在1NF中,原子性意味着在当前的业务上下文中,该属性不应该再被拆分为更小的独立查询单元。
关系数据库设计通常默认满足1NF:现代数据库系统在设计表时,只要你不在一个列中存储多值(比如JSON、数组等特殊类型),并且使用主键,那么你的表就是1NF的。但要注意,有些数据库支持JSON、数组等复合类型,如果你使用这些类型存储多个值,从关系模型的角度看,它依然违反了1NF的原子性原则,不过在NoSQL风格的设计中有时会被接受。
不要过度拆分:有时为了满足1NF而拆分得太细,可能导致查询时需要大量JOIN,反而影响性能。在实际设计中,需要在规范化和实际需求之间找到平衡。
六、练习与思考
1、以下表是否符合1NF?如果不符合,请修改。
答案:不符合,products 列是非原子的。应拆分为 order_items 表,每行一个产品。
2、假设有一张 teachers 表,包含 teacher_id、name、subject1、subject2、subject3 表示教师能教授的科目。这种设计有何问题?如何改进?
问题:重复组,最多只能存储3门课,且查询不便。应拆分为 teachers 和 teacher_subjects 表,一对多关系。
七、总结
第一范式(1NF) 要求表中的每一列都是原子性的,每一行有唯一标识。
违反1NF的典型情况包括:列中存储多个值、重复组、缺少主键。
转换为1NF的方法通常是将多值属性拆分成多行(子表),或为重复组创建关联表。
满足1NF是关系数据库设计的基础,但并不等于完美设计,还需要考虑更高范式和性能需求。

发表评论
所有评论