引言
在现代信息系统中,数据库对于存储和管理数据至关重要。为了确保数据的完整性和一致性,需要遵循数据规范化的原则。数据库范式提供了用于组织和结构化数据的指导准则,从而优化数据存储和检索效率。
第一范式 (1NF)
1NF 要求表中的每列都包含原子值(不可再分的数据项)。换句话说,表中的每个单元格只能包含单个值,不能包含列表或数组。
例如,考虑以下违反 1NF 的表:
姓名 | 电话 | 地址 | 爱好 |
---|---|---|---|
约翰·史密斯 | 555-1234, 555-5678 | 123 Main St | 足球, 音乐 |
此表违反 1NF,因为 "电话" 和 "爱好" 列包含多个值。我们可以将表规范化为 1NF,如下所示:
姓名 | 电话 | 地址 |
---|---|---|
约翰·史密斯 | 555-1234 | 123 Main St |
约翰·史密斯 | 555-5678 | 123 Main St |
| 爱好 | |---|---| | 足球 | | 音乐 |
第二范式 (2NF)
2NF 要求表中的每列都完全依赖于表的主键。这意味着表中的每列都必须与主键相关联,并且不能依赖于其他非主键列。
例如,考虑以下违反 2NF 的表:
订单 | 产品 | 数量 | 价格 |
---|---|---|---|
1 | 书籍 | 10 | 10 |
2 | 书籍 | 5 | 5 |
3 | CD | 15 | 15 |
4 | CD | 10 | 10 |
此表违反 2NF,因为 "价格" 列依赖于 "产品" 列,而不是主键 "订单"。我们可以将表规范化为 2NF,如下所示:
订单 | 产品 | 数量 |
---|---|---|
1 | 书籍 | 10 |
2 | 书籍 | 5 |
3 | CD | 15 |
4 | CD | 10 |
产品 | 价格 |
---|---|
书籍 | 10 |
CD | 15 |
第三范式 (3NF)
3NF 要求表中的每列都必须与主键完全依赖,并且不能传递依赖于其他列。换句话说,表中的每列必须直接与主键相关联,而不能间接地通过另一个非主键列相关联。
例如,考虑以下违反 3NF 的表:
订单 | 产品 | 数量 | 客户 |
---|---|---|---|
1 | 书籍 | 10 | 约翰·史密斯 |
2 | 书籍 | 5 | 玛丽·琼斯 |
3 | CD | 15 | 彼得·帕克 |
4 | CD | 10 | 约翰·史密斯 |
此表违反 3NF,因为 "客户" 列依赖于 "订单" 列,但 "订单" 列并不是主键。我们可以将表规范化为 3NF,如下所示:
订单 | 产品 | 数量 |
---|---|---|
1 | 书籍 | 10 |
2 | 书籍 | 5 |
3 | CD | 15 |
4 | CD | 10 |
| 客户 | |---|---| | 约翰·史密斯 | | 玛丽·琼斯 | | 彼得·帕克 |
要点总结
- 数据库范式是组织和结构化数据的指南。
- 1NF 确保表中的每列包含原子值。
- 2NF 要求表中的每列都依赖于主键。
- 3NF 要求表中的每列都直接依赖于主键,而不能传递依赖于其他列。
- 遵循数据库范式可提高数据完整性、一致性和可维护性。
示例代码
可以使用 SQL 语句实现数据库范式化。以下示例演示如何将违反 1NF 的表规范化为 1NF:
CREATE TABLE orders (
order_id INTEGER PRIMARY KEY,
customer_id INTEGER,
product_id INTEGER,
quantity INTEGER
);
ALTER TABLE orders
DROP COLUMN phones,
DROP COLUMN hobbies;
CREATE TABLE phones (
customer_id INTEGER PRIMARY KEY,
phone_number VARCHAR(255)
);
CREATE TABLE hobbies (
customer_id INTEGER PRIMARY KEY,
hobby VARCHAR(255)
);
INSERT INTO orders (order_id, customer_id, product_id, quantity)
SELECT order_id, customer_id, product_id, quantity
FROM old_orders;
INSERT INTO phones (customer_id, phone_number)
SELECT customer_id, phone_number
FROM old_orders;
INSERT INTO hobbies (customer_id, hobby)
SELECT customer_id, hobby
FROM old_orders;