小白学习MySQL Day21-23 20240908-09010

一、规范化 Normalisation

(1) 数据冗余 Data Redundancy
        数据在 多个地方重复存储,增加了数据不一致的风险。
        增加了内存使用量(memory usage),可能导致更新异常。
(2) 更新异常 Update Anomalies
        数据不一致(在更新数据时,如果只更新了部分冗余数据,而未更新其他部分导致的)
示例:
上表中存在数据冗余的情况。
多个员工可能属于同一个分支(如B003),但分支的地址信息在每条记录中都重复存储了。
如果需要更新某个分支的地址(如B003的地址),则必须更新所有属于该分支的员工的记录,否则就会出现更新异常。
更新异常的具体类型:
1) 插入异常(Insert Anomalies):
由于员工编号(staffNo)被设定为主键,在没有指定至少一个属于该新分支的员工的情况下,无法仅添加分支信息。
同时,每次添加新员工时,都必须确保为该员工指定了正确的分支信息。
2) 删除异常(Delete Anomalies):
删除一个分支的最后一个员工也会删除该分支的信息。
如果分支信息(如分支编号和地址)仅通过属于该分支的员工记录来存储,并且没有单独的分支表来维护这些信息,那么当删除最后一个属于该分支的员工记录时,该分支的所有信息也将丢失。
3) 修改异常(Modification Anomalies):
为了更改一个分支的信息,该分支内的所有员工(行)也必须进行更新。
如果分支信息分散存储在每个属于该分支的员工记录中,那么当需要更改分支的某些信息(如地址)时,必须更新该分支内每个员工的记录中的相应信息。
这不仅效率低下,而且容易出错,可能导致数据不一致。
(3) 规范化

通过分解表来减少数据冗余的过程,是一种将数据重新组织到多个相关表中的技术。

re-organising data into multiple related tables, so that data redundancy is minimised. 
How to Re-organise Tables?
        • The StaffBranch table is better split into the Staff table and the Branch table.
What information can help us to redesign tables?
Step 1: Observe the data in the table and find out the relationship between attributes.
Step 2: Regroup attributes based on attributes' context and split the big table.
ER建模与规范化
• ER图:Create tables
用于在数据库设计的早期阶段,在拥有详细的数据库规范,但没有表时。
• 规范化:Inprove tables
用于在已有数据库的基础上,但表的设计不佳时,可以使用规范化技术来改进表。
(4) 函数依赖 Functional Dependency
A method for finding relationships between attributes within a table
数据库设计中描述属性集之间关系。
“If A and B are attribute sets of relation R, B is functionally dependent on A
(denoted A → B), if each value of A in R is associated with exactly one value of B in R.”

如果 A 和 B 是关系 R 的属性集,B 函数依赖于 A(表示为 A→B),

如果关系 R 中 A 的每个值都与 R 中 B 的恰好一个值相关联

• A 被称为决定因素 determinant

The concept of FD is closely related to M:1 and 1:1 relationships.
 函数依赖的概念与 M:1 和 1:1 关系密切相关。
例1:
如何判断A与B之间的关系:先从A的角度出发,再从B的角度出发,
每个staffNo员工编号,只对应唯一一个sName、position、salary。
对于一个position或branchNo或bAddress,有多个staffNo。
因此,staffNo与sName、position、salary、branchNo和bAddress之间存在多对一(M:1)关系。
staffNo has M:1 relationship with sName, position, salary, branchNo and bAddress
每个branchNo分支编号,只与一个独特的bAddress相关联。
一个独特的bAddress只与一个branchNo相关联?
因此,branchNo与bAddress之间存在一对一(1:1)关系。
branchNo has a 1:1 relationship with bAddress.
• staffNo→ sName, position, salary, branchNo, bAddress
• branchNo→ bAddress
例2:
For the attributes below:
We assume each Lecturer has an unique email address (1:1),
   several students have one personal tutor (M:1).
Obvious FDs:  LecID → LName, Lemail
Each LecID of a lecturer is associated with exactly one lecturer name and his email address.
StudentID → Sname
Given a studentID, you can find that student’s name.
Other FD considerations:
LName & LecID
Two staffs may have the same name. Thus one name might be associated with two IDs.
StudentID → LecID
Given a student id, there will be a personal tutor assigned to him.
LecID & Sname
Given a lecturer ID, it is associated with one unique student name?
No, a lecturer has many students as personal tutees.
LEmail → LecID, LName
This is another valid FD if email addresses are unique to lecturers.
If these attributes are put together, they can form a relation, with the determinant being the unique key or primary key of the relation.
  For example:
LecID → LName, LEmail
StudentID → SName, LecID
  Or:
LEmail → LecID, LName
StudentID → SName, LEmail
1)部分函数依赖 Partial Functional Dependency

在关系模式R(U)中,如果X→Y,并且存在X的一个真子集X₀,使得X₀→Y也成立,

则称Y对X部分函数依赖。这意味着Y的值不仅依赖于X的全部,还依赖于X的某个真子集

  • 非唯一性:Y的值不是仅由X的全部属性唯一确定的,而是可以由X的某个真子集确定。
  • 冗余性:这种依赖关系可能导致数据冗余,因为Y的值可以通过X的多个子集得到。
  • Determinants in partial functional dependencies will become super keys.
        决定因素X可能成为 超键(Super Key)

示例

考虑一个学生选课的关系模式,包含属性集{学号, 姓名, 课程号, 成绩}。

如果学号和姓名的组合可以确定一个学生的成绩(即(学号, 姓名)→ 成绩),

但单独学号或单独姓名也能确定成绩(即学号→成绩,姓名→成绩),

则成绩对学号和姓名的组合是部分函数依赖的。

例2中的LecID, LName, LEmail → LName, LEmail。staffNo, sName → branchNo。

2)完全函数依赖 Full Functional Dependency

在关系模式R(U)中,如果X→Y,并且不存在X的任何真子集X₀,使得X₀→Y也成立,

则称Y对X完全函数依赖。这意味着Y的值完全由X的全部属性唯一确定,而不是X的任何真子集。

  • 唯一性:Y的值仅由X的全部属性唯一确定,不存在其他更小的子集能确定Y。
  • 非冗余性:完全函数依赖有助于减少数据冗余,因为Y的值不能通过X的任何真子集得到。
  • Determinants in full functional dependencies will become candidate keys if we split the table.

        决定因素X在新的表中可能会成为候选键(Candidate Key)

示例

在成绩表(学号, 课程号, 成绩)的关系中,

成绩完全依赖于学号和课程号的组合(即(学号, 课程号)→ 成绩)。

单独知道学号或课程号是无法确定成绩的,只有同时知道学号和课程号,才能唯一确定一个学生的某门课程的成绩。

例2中的 staffNo → branchNo。

3) 传递依赖 Transitive Dependency
Transitive dependency describes a condition where A, B, and C are attributes of a relation such that if A → B and B → C, then C is transitively dependent on A via B (provided that A is
not functionally dependent on B or C).

传递依赖描述了一个关系中的属性A、B和C之间的一种条件,即如果A → B且B → C,那么C就通过B传递依赖于A(前提是A不是直接函数依赖于B或C)。

(5)超键 Super Key 

能够唯一标识表中每一行记录(元组)的属性集,称为超键。

  • 唯一性:没有两行数据拥有完全相同的超键值
  • 可包含冗余属性:超键可以包含多余的信息。即使移除某些属性,只要剩余的属性集仍然能唯一标识元组,那么它仍然是超键。
  • 多个超键可能存在:一个表中可能有多个超键,每个超键都能唯一标识表中的每一行数据。

(6)候选键 Candidate Key

能够唯一标识表中每一行记录(元组)的最小属性集称为候选键。

  • 唯一性:没有两行数据拥有完全相同的候选键值。
  • 最小性:候选键不包含任何不必要的属性,即去掉任何一个属性都会导致它无法再唯一标识表中的记录。
  • 多个候选键可能存在:一个表中可能有多个候选键,每个都能唯一标识表中的每一行数据。

超键候选键,是一个或多个属性的集合,通过它可以唯一确定数据库表中的一个元组。

主键是表中选定的一个候选键,用于唯一标识表中的每一行记录。在大多数情况下,表中会选择一个候选键作为主键,但理论上可以选择任何候选键作为主键。

E.g. 有一个学生表,其中包含学号、姓名、性别等属性。

(学号、姓名、性别)可以作为一个超键,因为它能唯一标识一个学生。但是,这个超键包含了多余的属性,因为学号本身就能唯一标识一个学生。

学号可以作为一个候选键,因为它能唯一标识一个学生,且不包含多余的属性。

同样地,如果姓名没有重名,那么姓名也可以作为一个候选键。

The determinant has a M:1 or 1:1 relationship with other attributes in FDs.
在函数依赖中,决定因素与其他属性之间存在多对一(M:1)或一对一(1:1)的关系。
Two staff members may have the same name.
   Thus, one staff name can be associated with more than one staff number.
      StaffNo : sName  (M:1)
Two staff members may have the same position.
  Thus, one position may be associated with more than one staff number
      StaffNo : branchNo (M:1)

二、范式 Normal Forms

The Process of Normalisation 数据库规范化的过程

1、第一范式 First Normal Form (1NF)

如果一个关系(表)满足 “表中的所有数据值都是原子的,即:表项应该是单一的值,而不是集合或复合对象这一条件,则称该关系处于第一范式(1NF)。

All data values should be atomic.

Table entries should be single values, not sets or composite objects.

第一范式确保了数据库表中的每一列都只能包含单一的值。

如果关系中的某些数据值不是原子的,即包含了集合、列表、数组或其他复合数据类型,

那么该关系就处于未规范化形式(0NF),需要进行规范化处理以达到第一范式的要求。 

Look at “Texts” attribute:
To update the textbook name “T1” to something else, you need to manually update all “T1”s.
  “T1”被多次引用,则需要确保每个引用都得到了更新,这是一个繁琐且容易出错的过程。
To delete T1 from the pool of textbooks, you need to manually do so, too.
  遍历整个数据库,找到所有引用“T1”的地方,并将其删除或替换为其他教科书名称。
You cannot add a textbook without giving the information of Module (because Module is a   Primary Key). 如果所需的Module尚未定义,就无法添加新的教科书。
Normalise 0NF to 1NF
  • 方法一 Method 1:

(1) 去除重复组 Remove the repeating group:
通过 在包含重复数据的空列 (例中的Texts列) 中输入适当的数据,来消除重复组。
展平表格‘flattening’ the table
(2) 分配新主键 Assign a new primary/unique key 
为扁平化后的新表分配一个新的主键。
这个主键应该是唯一的,用于唯一标识表中的每一行。
主键可以是单个字段,也可以是多个字段的组合,即复合主键。
Problems in 1NF
Changing module code from “M1” to something else requires you to check the whole table.
Adding a new lecturer with no modules and text is impossible.
If a (department, lecturer) pair is modified , the change must be made to all (Module, Text) pairs.
   For example, to change (D1, L1) to some other value, you must manually change the first four      rows.
If (M3, T4) is deleted , L2 will be permanently lost!
  • 方法二 Method 2:
(1) 识别主键/唯一键。
(2) 将重复的数据和唯一键属性的一个副本放入一个单独的关系表中。

2、第二范式 Second Normal Form (2NF)

如果一个关系(表)满足以下两个条件:
1. 满足第一范式,即表中的所有数据值都是原子的。
2.关系的 所有非主键属性必须完全依赖于主键,而不是仅仅依赖于主键的一部分。
即: 对于关系中的每一个非主键属性B
必须存在从整个主键A到B的函数依赖A → B
不存在从主键A的某个真子集C(C ⊂ A)到B的部分函数依赖C → B
则称该关系处于第二范式(2NF)。
第二范式确保了关系中的非主键属性不会因主键的某一部分发生变化而受到影响,从而避免了数据冗余和更新异常。同时,它也保证了关系中的每一行都是唯一确定的,由完整的主键来唯一标识。
Normalise 1NF to 2NF
1、确定主键:明确每个关系(表)的主键,即能够唯一标识表中每一行记录的列或列的组合。
2、分析与检查函数依赖:确定哪些属性(或属性组)的值决定了其他属性的值。
                                          检查是否存在部分依赖。
3、分解关系以消除部分依赖:通过创建新的关系(表)来消除部分依赖。
将依赖于主键某一部分的非主键属性及其对应的主键部分移至新表中,而原表保留未被部分依赖影响的剩余主键部分。
这样,新表的主键将是原表中被部分依赖所特指的那一部分主键,从而消除了部分依赖,并使数据更加规范化。
4、确保新表也符合1NF:在创建新表时,必须确保新表同样满足第一范式的要求。

示例: 假设有一个表StudentCourses,用于记录学生选修的课程信息。

这个表包含以下字段: StudentID, CourseID, CourseName, Semester, Instructor。

StudentID和CourseID共同作为主键,即复合主键,它们一起能够唯一标识表中的每一行。

然而,CourseName和Instructor这两个字段实际上只依赖于CourseID,而不是主键的全部(StudentID和CourseID)。这构成了一个部分依赖。

为了消除这种部分依赖,我们可以将CourseName和Instructor以及它们所依赖的CourseID移至一个新表中Courses中。

同时,原表StudentCourses将保留StudentID、CourseID、Semester这些字段,但不再包含CourseName和Instructor,因为这两个字段现在由Courses表管理。

StudentCourses表仅包含与选课记录直接相关的信息(学生和课程之间的关联,以及学期),

而Courses表则管理课程本身的信息(CourseName和Instructor)。

这样就消除了对主键的部分依赖,并使数据更加规范化。

同时,这也减少了数据冗余,同一门课程的信息不再在每个选课记录中重复。

Problems in 2NF: 
Look at the table 2NFa
We cannot add a lecturer who is not assigned with any module.
  Because module is the primary key.
This is a theoretical discussion. Similar issues can be a real problem in some other tables.
By deleting M3, we lose L2 forever.
To change the department for L1, we need to change multiple rows manually.

3、第三范式 Third Normal Form (3NF)

如果一个关系(表)满足以下条件:
1. 满足第二范式:即表中的每个非主属性完全依赖于候选键。
              (候选键是表中能够唯一标识一条记录的属性或属性组合,主键是候选键的一个特例) 
2. 消除传递依赖
表中的 每个非键属性必须直接依赖于主键,而不能通过其他非键属性间接依赖于主键。
No non-key attribute is transitively dependent on the primary key .
非主属性之间不存在函数依赖关系
则称该关系处于第三范式(3NF)。
Problems Resolved in 3NF:  
Problems in 2NFa:
        • INSERT: Can't add lecturers who teach no modules
        • UPDATE: To change the department for L1 we must alter two rows
        • DELETE: If we delete M3 we delete L2 as well
In 3NF all of these are resolved (for this relation – but 3NF can still have anomalies!)
Normalise 2NF to 3NF
1、确定主键:明确每个关系(表)的主键,即能够唯一标识表中每一行记录的列或列的组合。
2、分析与检查函数依赖:确定哪些属性(或属性组)的值决定了其他属性的值。
                                          检查是否存在 传递依赖
                                    (非主键字段依赖于另一个非主键字段,而这个非主键字段又依赖于主键)
3、分解关系以消除传递依赖:通过创建新的关系(表)来消除部分依赖。
将这些传递依赖的属性和它们的决定因素(即被依赖的非主键属性)移动到一个新的表1中。
同时,在新的表2中,保留决定因素的一个副本(通常是主键或外键)。
这样,原关系中的所有非主键字段都将直接依赖于主键,从而满足3NF的要求。
4、确保新表也符合2NF:在创建新表时,必须确保新表同样满足第二范式的要求。
注:字段=列=属性

示例

订单ID客户ID客户名称订单金额运送公司运送经理
O001C001阿里巴巴1000顺丰张经理
O002C002京东1500圆通

王经理

假设订单ID是主键,则:订单ID → 运送公司 → 运送经理

“运送经理”这个非键属性传递依赖于“运送公司”,而“运送公司”又依赖于“订单ID”。

为了符合第三范式,我们可以将表进行分解:

重构后的表:

1.订单表:

订单ID客户ID客户名称订单金额运送公司
O001C001阿里巴巴1000顺丰
O002C002京东1500圆通
 

2.运送公司信息表:

运送公司运送经理
顺丰张经理
圆通王经理

LecID (A) → LEmail (B) → LName (C)
   Not a transitive dependency. Because LEmail is functionally dependent on LecID.

尽管 LEcID → LEmail → LName 链是传递的,但这种传递性并不构成拆分表的充分理由。

我们关注的是那种可能导致数据冗余和更新异常的传递依赖,而不仅仅是形式上的传递关系。

The type of transitive dependencies we are looking for should support relationships, or foreign keys.

拆分表的必要条件

1.  staffNo (A) → branchNo (B) → bAddress (C):典型的传递依赖

staffNo 直接决定了 branchNo,而 branchNo 又决定了 bAddress。

这里,bAddress 对 staffNo 的依赖是传递的,因为 staffNo 不直接决定 bAddress。

在这种情况下,可能会考虑拆分表以减少数据冗余和提高数据一致性。

2. LecID (A) → LEmail (B) → LName (C):并不构成需要拆表的传递依赖。

 LecID → LName 也成立,LName 实际上也直接依赖于 LecID。

因此,虽然 LName 可以通过 LEmail 间接依赖于 LecID,但这种依赖不是拆分表的必要条件。

三、示例

有一个表示在线商店订单的表格,表格中的每一条记录代表一个订单中的一个商品。
每个订单属于一个特定的客户,而每个客户只有一个地址。每个产品都有一个固定的价格。
表格的列包括:{订单号, 产品, 客户, 地址, 数量, 单价}。
                        {order, product, customer, address, quantity, unitPrice}
例如:(001, Laptop, Xiaobai, ChinaJiangsu, 1, $500) 。
主键是{订单号, 产品},表示每个订单中的每个产品都是唯一的,没有其他候选键。
任务是将这个表格规范化到第三范式(3NF)。
此表格已处于1NF。
1、确定主键:  {order, product}
2、分析与检查函数依赖:
" Each order is for a single customer and each customer has a single address."
        • {order} →{customer, address} 部分函数依赖
        • {order} → {customer} → {address} 部分函数依赖、传递依赖
"Each product has a single price."
        • {product} →{unitPrice} 部分函数依赖
"Each order transitively determines address via customer."
        • {order} → {customer} → {address} 部分函数依赖、传递依赖
Normalisation to 2NF
2NF: no partial dependencies on candidate keys
需解决两个部分函数依赖:{order} → {customer, address} , {product} → {unitPrice}
(1) To remove {order} → {customer, address}, we move {customer, address} to another relation, along with a copy of its determinant, order.
注:下划线的是每个表中的主键
R1: {order, customer, address} 
With remaining relation R2: {order, product, quantity, unitPrice}
(2)There is a partial FD in R2: {Product} → {UnitPrice}
To remove this, we move it to another relation R3 拆分R2,得到R3和R4
  R3: {Product, unitPrice}
and with remaining relation R4: {order, product, quantity}
Normalisation to 3NF
R1 has a transitive FD on its key 需要解决一个传递依赖
To remove {order} → {customer} → {Address}, decompose R1 over: 分解R1为R5和R6
R5: {order, customer}
R6: {customer, address}
总结
• 1NF: {order, product, customer, address, quantity, unitPrice}
• 2NF:
R1: {order, customer, address}      2NF
R3: {product, unitPrice}                  3NF
R4: {order, product, quantity}        3NF
• 3NF:
R3: {product, unitPrice}                  3NF
R4: {order, product, quantity}        3NF
R5: {order, customer}                     3NF
R6: {customer, address}                3NF

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值