Mysql——三大范式

什么是范式?

范式是数据库设计时遵循的一种规范,不同的规范要求遵循不同的范式。

常用的三大范式

  • 第一范式(1NF):属性不可分割,即每个属性都是不可分割的原子项。(实体的属性即表中的列)
  • 第二范式(2NF):满足第一范式;且不存在部分依赖,即非主属性必须完全依赖于主属性。(主属性即主键;完全依赖是针对于联合主键的情况,非主键列不能只依赖于主键的一部分)
  • 第三范式(3NF):满足第二范式;且不存在传递依赖,即非主属性不能与非主属性之间有依赖关系,非主属性必须直接依赖于主属性,不能间接依赖主属性。(A -> B, B ->C, A -> C)

举例说明3NF:

1NF

属性不可再分,即表中的每个列都不可以再进行拆分。

如下学生信息表(student):
id、name(姓名)、sex_code(性别代号)、sex_desc(性别描述)、contact(联系方式)
primary key(id)

idnamesex_codesex_desccontact
001张三017835201234_山西省运城市xx村
002李四017735204567_山西省吕梁市yy村
003王五118835207890_山西省太原市zz村

如果在查询学生表时经常用到学生的电话号,则应该将联系方式(contact)这一列分为电话号(phone)和地址(address)两列,这样才符合第一范式。

修改使表满足1NF后:

idnamesex_codesex_descphoneaddress
001张三017835201234山西省运城市xx村
002李四017735204567山西省吕梁市yy村
003王五118835207890山西省太原市zz村

判断表是否符合第一范式,列是否可以再分,得看需求,如果将电话号和地址分开才能满足查询等需求时,那之前的表设计就是不满足1NF的,如果电话号和地址拼接作为一个字段也可以满足查询、存储等需求时,那它就满足1NF。

2NF

在满足1NF的前提下,表中不存在部分依赖,非主键列要完全依赖于主键。(主要是说在联合主键的情况下,非主键列不能只依赖于主键的一部分)

如下学生成绩表(score):

stu_id(学生id)、kc_id(课程id)、score(分数)、kc_name(课程名)
primary key(stu_id, kc_id)

stu_idkc_idscorekc_name
001101185高数3-1
001102279计算机组成原理
002101159.9高数3-1

表中主键为stu_id和kc_id组成的联合主键。满足1NF;非主键列score完全依赖于主键,stu_id和kc_id两个值才能决定score的值;而kc_name只依赖于kc_id,与stu_id没有依赖关系,它不完全依赖于主键,只依赖于主键的一部分,不符合2NF。

修改使表满足2NF后:

成绩表(score) primary key(stu_id)

stu_idkc_idscore
001101185
001102279
002101159.9

课程表(kc) primary key(kc_id)

kc_idkc_name
1011高数3-1
1022计算机组成原理

将原来的成绩表(score)拆分为成绩表(score)和课程表(kc),而且两个表都符合2NF。

3NF

在满足2NF的前提下,不存在传递依赖。(A -> B, B -> C, A->C)

如下学生信息表(student):

primary key(id)

idnamesex_codesex_descphoneaddress
001张三017835201234山西省运城市xx村
002李四017735204567山西省吕梁市yy村
003王五118835207890山西省太原市zz村

表中sex_desc依赖于sex_code,而sex_code依赖于id(主键),从而推出sex_desc依赖于id(主键);sex_desc不直接依赖于主键,而是通过依赖于非主键列而依赖于主键,属于传递依赖,不符合3NF。

修改表使满足3NF后:

学生表(student) primary key(id)

idnamesex_codephoneaddress
001张三017835201234山西省运城市xx村
002李四017735204567山西省吕梁市yy村
003王五118835207890山西省太原市zz村

性别代码表(sexcode) primary key(sex_code)

sex_codesex_desc
0
1

将原来的student表进行拆分后,两个表都满足3NF。

什么样的表越容易符合3NF?

非主键列越少的表。(1NF强调列不可再分;2NF和3NF强调非主属性列和主属性列之间的关系)
如代码表(sexcode),非主键列只有一个sex_desc;
或者将学生表的主键设计为primary key(id,name,sex_code,phone),这样非主键列只有address,更容易符合3NF。

### MySQL 数据库设计三大范式解释 #### 一、第一范式 (1NF) 第一范式规定数据库表的每一列都是不可分割的基本数据项,即实体中的某个属性不能有多个值,必须保证每列原子性。这意味着每个字段只包含单一值,不允许列表或其他复合结构。 例如,在用户信息表中不应存在如下情况: | 用户ID | 姓名 | |--------|------------| | 1 | 张三, 李四 | 而是应该拆分为两个独立记录[^1]。 ```sql CREATE TABLE Users ( UserID INT PRIMARY KEY, Name VARCHAR(255) ); ``` #### 二、第二范式 (2NF) 当满足第一范式的要求之后,还需进一步消除部分依赖才能达到第二范式。具体而言就是非主键字段应完全函数依赖于整个候选码而非其一部分。简单地说就是在已经符合1NF的基础上去除重复组群的数据冗余问题。 考虑订单详情表的例子,其中包含了产品编号、名称以及单价等信息。由于这些信息实际上仅与特定的产品有关联而不是具体的某次购买行为本身,因此应当将其分离出来形成单独的产品表。 ```sql -- 错误示范:违反2NF CREATE TABLE OrderDetails ( OrderID INT, ProductCode CHAR(8), ProductName VARCHAR(255), -- 应该移到Product表里 UnitPrice DECIMAL(10, 2) -- 同上 ); -- 正确做法 CREATE TABLE Products ( ProductCode CHAR(8) PRIMARY KEY, ProductName VARCHAR(255), UnitPrice DECIMAL(10, 2) ); CREATE TABLE Orders ( OrderID INT AUTO_INCREMENT PRIMARY KEY, CustomerID INT NOT NULL, FOREIGN KEY (CustomerID) REFERENCES Customers(CustomerID) ); CREATE TABLE OrderItems ( OrderItemID INT AUTO_INCREMENT PRIMARY KEY, OrderID INT NOT NULL, ProductCode CHAR(8) NOT NULL, Quantity SMALLINT UNSIGNED DEFAULT '1', FOREIGN KEY (OrderID) REFERENCES Orders(OrderID), FOREIGN KEY (ProductCode) REFERENCES Products(ProductCode) ); ``` #### 三、第三范式 (3NF) 在遵循前两者的前提下,还需要移除传递依赖——即任何非主键字段不得间接依赖其他非主键字段。换句话说就是要确保所有的非主属性都直接取决于唯一的主关键字。 假设有一个员工薪资历史记录表,里面不仅保存着工资数额还记载了对应的职位等级。然而事实上职级变化往往伴随着薪酬调整,所以这里存在着潜在的风险:一旦职务发生变动就可能导致旧版本的信息不一致。为了避免这种情况的发生,最好创建一个新的表格专门用于追踪职业发展轨迹。 ```sql -- 不推荐的方式:违反3NF CREATE TABLE SalaryHistory ( EmployeeID INT, EffectiveDate DATE, PositionLevel TINYINT, MonthlySalary DECIMAL(10, 2) ); -- 推荐方式 CREATE TABLE Positions ( PositionID SERIAL PRIMARY KEY, Title VARCHAR(64), Level TINYINT ); CREATE TABLE EmploymentRecords ( RecordID BIGSERIAL PRIMARY KEY, EmployeeID INT NOT NULL, StartDate DATE NOT NULL, EndDate DATE, PositionID INT NOT NULL, FOREIGN KEY (EmployeeID) REFERENCES Employees(EmployeeID), FOREIGN KEY (PositionID) REFERENCES Positions(PositionID) ); CREATE TABLE Salaries ( SalaryID BIGSERIAL PRIMARY KEY, EmployeeID INT NOT NULL, EffectiveFrom DATE NOT NULL, AmountPerMonth DECIMAL(10, 2) CHECK(AmountPerMonth >= 0), FOREIGN KEY (EmployeeID) REFERENCES Employees(EmployeeID) ); ``` 通过上述措施能够有效减少数据冗余提高系统的稳定性和可扩展性,同时也便于后续的操作维护工作。不过值得注意的是,在实际项目开发过程中并非任何时候都需要严格遵守全部三个规范化标准;有时候为了优化性能或者其他特殊需求反而会选择适当放宽某些约束条件甚至采用去标准化策略[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值