数据库 第8章 关系数据库设计

Chapter 8: Relational Database Design

8.1 好的关系设计的特点(Features of Good Relational Design)

设计选择(Design Alternative):

  • Larger Schemas(更大的模式)
  • Smaller Schemas(更小的模式)

存储异常(Storage Anomaly)

(以图书管理系统中,个人信息是否应当与书本信息合并:不应该)

  • Data redundancy(数据冗余):当某人借书超过一本,其所在部门的信息被重复
  • Update anomaly(更新异常)/ Potential inconsistency(潜在的不一致性):当某个借书人所在部门需要更新时,由于数据冗余,可能发生更新不一致的情况
  • Insert anomaly(插入异常):如某个部门无人借书,则该部门信息无法存入
  • Delete anomaly(删除异常):如某个部门的人将书全部还清,则该部门信息被全部删除

关系模式

Def:由五部分组成,是一个五元组: R ( U , D , D O M , F ) R(U, D, DOM, F) R(U,D,DOM,F)

  • 关系名 R R R 是符号化的元组语义

  • U U U 为一组属性

  • D D D 为属性组 U U U 中的属性所来自的域

  • D O M DOM DOM 为属性到域的映射

  • F F F 为属性组 U U U 上的一组数据依赖

由于 D D D D O M DOM DOM 与模式设计关系不大,因此在本章中把关系模式看作一个三元组: R < U , F > R{\lt}U,F{\gt} R<U,F>

第一范式: 作为二维表,关系要符合一个最基本的条件:每个分量必须是不可分开的数据项。满足了这个条件的关系模式就属于第一范式(1NF)

数据依赖

多值依赖(MVD,Multi-Valued Dependency)(将在8.6节介绍)
函数依赖(FD,Functional Dependency)

Def:设 R ( U ) R(U) R(U) 是一个属性集 U U U 上的关系模式, X X X Y Y Y U U U 的子集。若对于 R ( U ) R(U) R(U) 的关系实例的任意两个可能的元组 r 1 r1 r1 r 2 r2 r2 ,若 r 1 [ X ] = r 2 [ X ] r1[X]=r2[X] r1[X]=r2[X] ,则 r 1 [ Y ] = r 2 [ Y ] r1[Y]=r2[Y] r1[Y]=r2[Y] ;或者,若 r 1 [ Y ] r1[Y] r1[Y] 不等于 r 2 [ Y ] r2[Y] r2[Y] ,则 r 1 [ X ] r1[X] r1[X] 不等于 r 2 [ X ] r2[X] r2[X] ;称 X X X 决定 Y Y Y, 或者 Y Y Y 依赖 X X X ,记为 X → Y X{\rightarrow}Y XY。其中 X X X 称为这个函数依赖的决定因素。

(相互依赖记为 X ↔ Y X{\leftrightarrow}Y XY Y Y Y 不依赖于 X X X 记为 X ↛ Y X{\nrightarrow}Y XY

(就是有种 X X X 对于 Y Y Y 来说是主键的感觉,这个箭头可以看作是数理逻辑中的“蕴含“,元组再某个属性组上取值相同时为真,不同时为假,则 X → Y X{\rightarrow}Y XY 的意义与函数依赖相同)

Attention:函数依赖不是某个关系实例应当满足的条件,而是所有关系模式 R R R 下所有关系实例均要满足的约束条件,即一个关系 r r r 满足 X → Y X{\rightarrow}Y XY 和在一个关系模式 R R R X → Y X{\rightarrow}Y XY 成立是不同的

平凡函数依赖:当 Y ⊆ X Y{\subseteq}X YX 时,显然 X → Y X{\rightarrow}Y XY ,称为平凡函数依赖;反之,若 Y ⊈ X Y{\nsubseteq}X YX 时且 X → Y X{\rightarrow}Y XY ,则称为 非平凡函数依赖

(平凡函数依赖没有什么特别的语义,我们所要求的语义都是非平凡函数依赖)

完全函数依赖:在 R ( U ) R(U) R(U) 中,若 X → Y X{\rightarrow}Y XY ,且对于 X X X 的任意一个真子集 X ′ ⊂ X X'{\subset}X XX ,都有 X ′ ↛ Y X'{\nrightarrow}Y XY ,则称 Y Y Y X X X 完全函数依赖;反之称为部分函数依赖

(部分依赖就是说 X X X 作为 Y Y Y 的“主码”有点冗余,其实不用那么多字段就可以决定 Y Y Y 的不同)

(部分函数依赖是产生储存异常的内在原因)

传递函数依赖: X X X Y Y Y Z Z Z 是关系 R R R 中互不相同的属性集合,若有 X → Y X{\rightarrow}Y XY Y → Z Y{\rightarrow}Z YZ,( Y ↛ X Y{\nrightarrow}X YX Z ⊈ Y Z{\not\subseteq}Y ZY)则称 Z Z Z 传递函数依赖于 X X X 。(若同时又 Y → X Y{\rightarrow}X YX,则 Z Z Z 实际上是直接依赖于 X X X

注意:每个部份函数依赖都是传递函数依赖,即 X → X ′ → Y X{\rightarrow}X'{\to}Y XXY

超码:对于 R < U , F > R{\lt}U,F{\gt} R<U,F> X ⊆ U X{\subseteq}U XU,若 F D FD FD 上成立 X → U X{\rightarrow}U XU,则称 X X X R R R 的一个超码

候选码:对超码 X X X ,若不存在 X X X 的真子集 X ′ ⊂ X X'{\subset}X XX ,使得 X ′ → U X'{\rightarrow}U XU,则称 X X X R R R 的一个候选码

(候选码就是最小的超码,适合用来做主键,候选码中的属性称作 主属性,其他称为非主属性)

全码:整个属性集 U U U 是候选码,称为全码(all-key)

外码:定义关系模式 R R R 中属性或属性组 X X X 并非 R R R 的码,但 X X X 是另一个关系模式的码,则称 X X X R R R 的外部码

有损分解A Lossy Decomposition):

Suppose we decompose
employee(ID, name, street, city, salary)
into
employee1 (ID, name)
employee2 (name, street, city, salary)
image

无损分解A Lossles Decomposition):

无损分解

关系 R < U , F > R{\lt}U,F{\gt} R<U,F> 分解为 R 1 R_1 R1 R 2 R_2 R2 ,当且仅当 R 1 ∩ R 2 → R 1   ∈   F + R_1{\cap}R_2{\to}R_1{\,}{\in}{\,}F^+ R1R2R1F+ R 1 ∩ R 2 → R 2   ∈   F + R_1{\cap}R_2{\to}R_2{\,}{\in}{\,}F^+ R1R2R2F+

8.2 原子域和第一范式(Atomic Domains and First Normal Form)

范式(Normal Form,NF):是符合某一种级别的关系模式的集合

范式的种类:
  • 第一范式(1NF)
  • 第二范式(2NF)
  • 第三范式(3NF)
  • BC范式(BCNF)
  • 第四范式(4NF)
  • 第五范式(5NF)

第一范式

Def:作为二维表,关系要符合一个最基本的条件:每个分量必须是不可分开的数据项。满足了这个条件的关系模式就属于第一范式(1NF)

(相对应的情况是多值属性、组合属性,例如 "CS101"可以被拆分为院系CS和课程号101)

第二范式

(第一范式会出现的问题在于,关系模式中一个或一些(但不是候选码中的全部)主属性就可以直接决定一些属性,并能与它们一起拆分开来形成一张新的表;第二范式解决了这个问题)

Def:若 R ⊆ 1 N F R{\subseteq}1NF R1NF,且每一个非主属性都完全函数依赖于 R R R 的主码,则 R ⊆ 2 N F R{\subseteq}2NF R2NF

(或者说, R R R 中任何一个非主属性都完全函数依赖于 R R R 的每一个候选码(因为任何一个候选码都可以作为主键,主键就是从候选码中选一个出来的))

反例:图书馆借阅登记的关系模式 B o r r o w ( L C N O ‾ , N a m e , D e p t , B N O ‾ , D a t e ) Borrow(\underline{LCNO}, Name, Dept, \underline{BNO}, Date) Borrow(LCNO,Name,Dept,BNO,Date) = {借书证号,借书人姓名,所在部门,图书号,借书日期},但是借书人姓名只依赖于借书证号,而不用同时依赖于图书登录号(属于第一范式而不属于第二范式)

(第一范式会出现的问题在于,关系模式中一个或一些(但不是候选码中的全部)主属性就可以直接决定一些属性,并能与它们一起拆分开来形成一张新的表;第二范式解决了这个问题)

Example:不属于第二范式会产生的异常:(以 S − L − C ( S n o ‾ , S d e p t , S l o c , C n o ‾ , G r a d e ) S-L-C(\underline{Sno},Sdept,Sloc,\underline{Cno},Grade) SLC(Sno,Sdept,Sloc,Cno,Grade) 为例)

  • 插入异常:如果插入一个还没选课的新学生,则主属性 C n o Cno Cno 就会为空,插入失败

  • 删除异常:如果有个学生只选了一门课,现在他不选了,则这个学生的信息就丢失了

  • 修改复杂:比如一个学生转专业,就会重复修改很多的元组

出现原因:例子中有两类非主属性:

  • G r a d e Grade Grade:它对码完全函数依赖
  • S d e p t Sdept Sdept S l o c Sloc Sloc:它们对码不是完全函数依赖,而是 S n o   → S d e p t Sno{\,}{\rightarrow}Sdept SnoSdept S l o c Sloc Sloc

解决方法:用投影分解把关系模式 S − L − C S-L-C SLC 分解成两个关系模式

  • S C ( S n o , C n o , G r a d e ) SC(Sno,Cno,Grade) SC(Sno,Cno,Grade)

  • S − L ( S n o , S d e p t , S l o c ) S-L(Sno,Sdept,Sloc) SL(Sno,Sdept,Sloc)

总结:当关系模式 R R R 不是 “good form” 的时候,将其进行分解,从而:

  • 每个分解成的子关系模式 R i R_i Ri 都是 “good form”
  • 每个分解成的子关系模式 R i R_i Ri 可以无损连接分解(有损连接分解例子参考上面的表格

8.3 使用函数依赖进行分解(Decomposition Using Functional Dependencies)

函数依赖

(第二范式会出现的问题在于,某些非主属性虽然依赖于某个候选码,但这种依赖不是直接的,而是通过传递依赖得到的,因此仍然会出现冗余)

换种说法更好理解

(第二范式会出现的问题在于,关系模式中的一些属性(这些属性并不完全包含某个候选码)就可以直接决定一些属性,并能与它们一起拆分开来形成一张新的表;第三范式解决了这个问题)

第三范式

Def 1:设 R R R 是一个关系模式,如果 R ∈ 1 N F R{\in}1NF R1NF ,并且 R R R 中不存在任何非主属性传递函数依赖于 R R R 的某个候选关键字(即候选码),则称 R R R 是第三范式的

Def 2:设 R R R 是一个关系模式, R ∈ 1 N F R{\in}1NF R1NF ,对于 R R R 上函数依赖的闭包 F + F^+ F+ 中的所有函数依赖 α → β \alpha\to \beta αβ ,以下一项至少成立:

  • α → β \alpha\to \beta αβ 是平凡函数依赖
  • α \alpha α R R R 的一个超码
  • β − α \beta - \alpha βα 中的每个属性都包含在 R R R 的一个候选码中(每个属性可以包含在不同的候选码中,不一定是同一个)(换句话说, β − α {\beta}-{\alpha} βα 中的属性都是主属性)

(Def 2 更好理解,对于情况 3,若有一个属性 A   ∈   β − α A{\,}{\in}{\,}{\beta}-{\alpha} Aβα A A A 不是主属性,那么存在传递函数依赖 候选码 → α → A \to\alpha\to A αA

数学描述:设关系模式 R < U , F > ∈ 1 N F R{\lt}U,F{\gt}∈1NF R<U,F>1NF ,若 R R R 中不存在这样的码 X X X 、属性组 Y Y Y 及非主属性 Z Z Z Y ⊄ Z Y{\not\subset}Z YZ), 使得 X → Y X→Y XY Y → Z Y→Z YZ成立, Y ↛ X Y{\nrightarrow}X YX不成立,则称 R < U , F > ∈ 3 N F R{\lt}U,F{\gt} ∈ 3NF R<U,F>3NF

Th:设 R R R 是一个关系模式,如果 R ∈ 3 N F R{\in}3NF R3NF,则必有 R ∈ 2 N F R{\in}2NF R2NF

反例:设关系模式 R = R= R=(账号,姓名,储蓄额,收储员,储蓄所名),其中 账号 是主码;“储蓄所名” 通过 “收储员” 依赖于 “账号”;(属于第二范式而不属于第三范式)

正例:图书馆借阅登记的关系模式 B o r r o w ( L C N O ‾ , N a m e , D e p t , B N O ‾ , D a t e ) Borrow(\underline{LCNO}, Name, Dept, \underline{BNO}, Date) Borrow(LCNO,Name,Dept,BNO,Date) = {借书证号,借书人姓名,所在部门,图书号,借书日期} 的一种分解方案: C A R D ( L C N O , N a m e , D e p t ) CARD(LCNO, Name, Dept) CARD(LCNO,Name,Dept) L O A N S ( L C N O , B N O , D a t e ) LOANS(LCNO, BNO, Date) LOANS(LCNO,BNO,Date) 3 N F 3NF 3NF

(第三范式解决了第二范式的问题,但是还有新的问题,即主属性对码可能存在部分函数依赖和传递函数依赖)

BCNF

Def 1:设 F F F 是关系模式 R R R 上的 F D FD FD 集,如果 R   ∈   1 N F R{\,}{\in}{\,}1NF R1NF,并且在 R R R 中无任何属性传递函数依赖于 R R R 中的任何一个码,则称关系模式 R R R 是属于 B C N F BCNF BCNF

Def 2:设 F F F 是关系模式 R R R 上的 F D FD FD 集,如果对于任一属性集 Y ⊂ R Y{\subset}R YR 和任一属性 A   ∈   R − Y A{\,}{\in}{\,}R-Y ARY。只要 Y → A Y{\to}A YA 成立, Y Y Y 必定是 R R R 的某个超码,则称关系模式 R R R 是属于 B C N F BCNF BCNF

(Def 2 比较好,说明BCNF的任何一条非平凡函数依赖的左部都可以作为超码

Th:设 R R R 是一个关系模式,如果 R ∈ B C N F R{\in}BCNF RBCNF,则必有 R ∈ 3 N F R{\in}3NF R3NF

性质

  • 所有非主属性都完全函数依赖于每个候选码
  • 所有主属性都完全函数依赖于每个不包含它的候选码
  • 没有任何属性完全函数依赖于非码的任何一组属性

B C N F BCNF BCNF 消除了第三范式的问题,实际上已经消除了插入异常和删除异常,即消除了所有基于函数依赖能够发现的冗余,实现了模式的彻底分解,达到了最高的规范化程度)

(也就是说,看起来没啥问题、不能再拆的一般就是 B C N F BCNF BCNF

反例:邮政编码关系模式 R ( C i t y , S t r e e t , Z i p ) R(City,Street,Zip) R(City,Street,Zip) F D FD FD { { C i t y , S t r e e t } → Z i p ,   Z i p → C i t y } \{ \{City,Street\}{\to} Zip,{\,}Zip{\to}City\} {{City,Street}Zip,ZipCity} (城市里有很多区县乡镇,每个区县乡镇的邮政编码相同,每个区县乡镇有很多街道,但一般来说同一个区县乡镇内不会有重名的街道);显然 R R R 中不存在非主属性,因为 { C i t y , S t r e e t } \{City,Street\} {City,Street} { Z i p , S t r e e t } \{Zip, Street\} {Zip,Street} 都是 R R R 的候选码,因此 R   ∈   3 N F R{\,}{\in}{\,}3NF R3NF,然而 C i t y City City 部分函数依赖于 { Z i p , S t r e e t } \{Zip, Street\} {Zip,Street} ,因此也是传递函数依赖于 { Z i p , S t r e e t } \{Zip, Street\} {Zip,Street} ,因而 R   ∉   B C N F R{\,}{\notin}{\,}BCNF R/BCNF (属于第三范式而不属于 B C N F BCNF BCNF

正例 1:关系模式 C ( C n o , C n a m e , P c n o ) C(Cno,Cname,Pcno) C(Cno,Cname,Pcno) ,只有一个码 C n o Cno Cno ,显然它是唯一的决定因素,因此 C   ∈   B C N F C{\,}{\in}{\,}BCNF CBCNF

正例 2:关系模式 S J P ( S , J , P ) SJP(S,J,P) SJP(S,J,P), 中, S S S 是学生, J J J 表示课程, P P P 表示名次,假设不存在并列名次,则 ( S , J ) (S,J) (S,J) ( J , P ) (J,P) (J,P) 都可以作为候选码,且没有其他决定因素,因此 S J P   ∈   B C N F SJP{\,}{\in}{\,}BCNF SJPBCNF

8.4 函数依赖理论(Functional-Dependency Theory)

函数依赖的闭包

Def:关系模式 R < U , F > R{\lt}U,F{\gt} R<U,F> 中任意一个关系 r r r ,若函数依赖 X → Y X{\to}Y XY 都成立,则称 F F F 逻辑蕴含 X → Y X{\to}Y XY

Def:设 F F F 是一个函数依赖集, F F F闭包 是被 F F F 逻辑蕴含的所有函数依赖的集合,记作 F + F^+ F+

Armstrong 公理系统
  • 自反reflexivity):如果 β ⊆ α {\beta}{\subseteq}{\alpha} βα,则 α → β {\alpha}{\to}{\beta} αβ
  • 增补augmentation):如果 α → β {\alpha}{\to}{\beta} αβ ,则 γ α → γ β {\gamma}{\alpha}{\to}{\gamma}{\beta} γαγβ
  • 传递transitivity):如果 α → β {\alpha}{\to}{\beta} αβ β → γ {\beta}{\to}{\gamma} βγ ,则 α → γ {\alpha}{\to}{\gamma} αγ

(Armstrong公理系统是有效且完善的,反复使用可以得到闭包 F + F^+ F+

(自反律的使用并不依靠于 F + F^+ F+

由上面三条基本公理,还可以得到一些推论:

  • 合并union):如果 α → β {\alpha}{\to}{\beta} αβ β → γ {\beta}{\to}{\gamma} βγ ,则 α → β γ {\alpha}{\to}{\beta}{\gamma} αβγ
  • 分解decomposition):如果 α → β γ {\alpha}{\to}{\beta}{\gamma} αβγ ,则 α → β {\alpha}{\to}{\beta} αβ β → γ {\beta}{\to}{\gamma} βγ
  • 伪传递pseudotransitivity):如果 α → β {\alpha}{\to}{\beta} αβ γ β → δ {\gamma}{\beta}{\to}{\delta} γβδ,则 α γ → δ {\alpha}{\gamma}{\to}{\delta} αγδ

引理 1 X → A 1 A 2 . . . A k X\to A_1A_2...A_k XA1A2...Ak 的重要条件是 X → A i ,   ( i = 1 , 2 , . . . , k ) X\to A_i,{\,}(i=1,2,...,k) XAi,(i=1,2,...,k) 成立

(我自己加一条:如果 α → β {\alpha}{\to}{\beta} αβ ,则 α γ → β {\alpha}\gamma{\to}{\beta} αγβ

属性集的闭包

Def 1:设 α {\alpha} α 是一个属性集,在函数依赖 F F F 下被 α {\alpha} α 确定的所有属性称为 F F F α \alpha α闭包,记为 α + {\alpha}^+ α+

Def 2:设 F F F 为属性集 U U U 上的一组函数依赖, X X X Y   ⊆   U Y{\,}{\subseteq}{\,}U YU X F + = { A   ∣   X → A X_F^+=\{A{\,}|{\,}X\to A XF+={AXA 能由 F F F 根据Armstrong公理导出 } \} } X F + X_F^+ XF+ 称为属性集 X X X 关于函数依赖集 F F F 的闭包

引理 2:设 F F F 为属性集 U U U 上的一组函数依赖, X X X Y   ⊆   U Y{\,}{\subseteq}{\,}U YU ,则 X → Y X \to Y XY 能由 F F F 根据 Armstrong公理导出的充分必要条件是: Y ⊆ X F + Y{\subseteq} X_F^+ YXF+

(由引理 2可知,要判断是否 X → Y X \to Y XY ,只需先求出 X F + X_F^+ XF+ ,再判断是否 Y ⊆ X F + Y{\subseteq} X_F^+ YXF+

算法:从 r e s u l t = α result={\alpha} result=α 开始,把能从 r e s u l t result result 的子集推导出来的属性全部加入 r e s u l t result result (就是遍历 F F F 中的每条函数依赖,若左部属于 r e s u l t result result,则将其右部加入 r e s u l t result result;反复遍历,直至 r e s u l t result result 不再改变为止)

U = { A , B , C , D , E } U=\{A, B, C, D, E\} U={A,B,C,D,E} F = A B → C , B → D , C → E , E C → B , A C → B F={AB→C, B→D, C→E, EC→B, AC→B} F=ABC,BD,CE,ECB,ACB

( A B ) F + = A B C D E (AB)_F^+=ABCDE (AB)F+=ABCDE

作用

  • α + {\alpha}^+ α+ 包括了所有属性,那么 α {\alpha} α 可作为该关系的主码
  • 计算 α + {\alpha}^+ α+ 同样也可以用作计算 F + F^+ F+,因为可以得到 α → γ {\alpha}{\to}{\gamma} αγ,其中 γ ⊆ α {\gamma}{\subseteq}{\alpha} γα

函数依赖的保持、等价与覆盖

Def:设 ρ = R 1 , R 2 , . . . R k {\rho}={R_1,R_2,...R_k} ρ=R1,R2,...Rk 是关系模式 R = < W , F > R={\lt}W,F{\gt} R=<W,F> 的一个分解;把 π R i ( F ) = { X → Y :   X → Y   ∈   F + {\pi}_{R_i}(F)=\{X{\to}Y:{\,}X{\to}Y{\,}{\in}{\,}F^+ πRi(F)={XY:XYF+ X ∪ Y   ⊆   R i } X{\cup}Y{\,}{\subseteq}{\,}R_i\} XYRi} 称为 F F F R i R_i Ri 上的投影。如果所有的投影的并集再去闭包还是原来的函数依赖,即 ( π R 1 ∪ π R 2 ∪ . . . ∪ π R k ) + = F + ({\pi}_{R_1}{\cup}{\pi}_{R_2}{\cup}...{\cup}{\pi}_{R_k})^+=F^+ (πR1πR2...πRk)+=F+ ,则称 ρ {\rho} ρ保持 F D FD FD F F F

(简单来说,就是把一个关系模式拆开来以后,原来的所有依赖是不是都还在(可能分散在各个拆开后的关系中),如果都在就叫保持 F D FD FD 集;有点像等价类的拆分?)

Def:若关系模式 R R R 上的两个两个 F D FD FD 集合 F F F G G G F + = G + F^+=G^+ F+=G+ ,则称 F F F G G G等价的,记为 F ≡ G F{\equiv}G FG

Def:若 F D FD FD F ≡ G F{\equiv}G FG ,则称 G G G F F F 的一个覆盖

引理 3 F + = G + F^+=G^+ F+=G+ 的充分必要条件是 F   ⊆   G + F{\,}{\subseteq}{\,}G^+ FG+ G   ⊆   F + G{\,}{\subseteq}{\,}F^+ GF+

极小函数依赖集

Def:如果函数依赖集 F F F 满足以下条件,称 F F F 为一个 极小函数依赖集 ,亦称为 最小依赖集最小覆盖

  • F F F 中任一函数依赖的右部仅含有一个属性
  • F F F 中不存在这样的函数依赖 X → A X\to A XA ,使得 F F F F − { X → A } F-\{X\to A\} F{XA} 等价
  • F F F 中不存在这样的函数依赖 X → A X\to A XA X X X 有真子集 Z Z Z 使得 F − { X → A } ∪ { Z → A } F-\{X\to A\}{\cup}\{Z\to A\} F{XA}{ZA} F F F 等价

(第二条代表 F F F 中的函数依赖均不能由 F F F 中其他函数依赖导出;第三条代表 F F F 中各函数依赖左部均为最小属性集,不存在冗余)

Th:任一函数依赖集 F F F 均等价于一个极小函数依赖集,记为 F m F_m Fm

算法

① 遍历 F F F 中每一条函数依赖 X → Y X\to Y XY ,若 Y = A 1 A 2 . . . A k ( k ≥ 2 ) Y=A_1A_2...A_k(k{\geq}2) Y=A1A2...Ak(k2),则用每一个 X → A i X\to A_i XAi 代替

② 遍历 F F F 中每一条函数依赖 X → A X\to A XA ,令 G = F − { X → A } G=F-\{X\to A\} G=F{XA} ,若 A ∈ X G + A{\in}X_G^+ AXG+ ,则删除此函数依赖

③ 遍历 F F F 中每一条函数依赖 X → A X\to A XA ,若 X = B 1 B 2 . . . B m ( m ≥ 2 ) X=B_1B_2...B_m(m{\geq}2) X=B1B2...Bm(m2) ,则逐一考察 B i B_i Bi ,若 A   ∈   ( X − B i ) F + A{\,}\in{\,}(X-B_i)_F^+ A(XBi)F+ ,则用 ( X − B i ) → A (X-B_i)\to A (XBi)A 取代 X → A X\to A XA

F F F 的最小依赖集 F m F_m Fm 并不一定是唯一的,它与具体的函数依赖以及 X → A X\to A XA X X X 各属性的处置顺序有关)

F = { A → B ,   B → A ,   B → C ,   A → C ,   C → A } F=\{A\to B,{\,}B\to A,{\,}B\to C,{\,}A\to C,{\,}C\to A\} F={AB,BA,BC,AC,CA} F m 1 F_{m1} Fm1 F m 2 F_{m2} Fm2 都是最小依赖集:

  • F m 1 = { A → B ,   B →   C ,   C → A } F_{m1} = \{A\to B,{\,}B\to{\,}C,{\,}C\to A\} Fm1={AB,BC,CA}
  • F m 2 = { A → B ,   B → A ,   A → C ,   C → A } F_{m2}=\{A\to B,{\,}B\to A,{\,}A\to C,{\,}C\to A\} Fm2={AB,BA,AC,CA}

正则覆盖

Def:如果去除某一函数依赖中的一个属性不改变整个函数依赖集的闭包,则称该属性对于该函数依赖是无关的extraneous

算法:对于函数依赖 α → β \alpha\to\beta αβ,想要判断 A A A 对于该函数依赖而言是否是无关的 :

① 若 A   ∈   α A{\,}{\in}{\,}\alpha Aα ,则计算 ( α − A ) + (\alpha-A)^+ (αA)+,若包括 β \beta β,则显然 A A A 对于 α → β \alpha\to\beta αβ 来说是无关的;(说明不需要 A A A 也可以推出 β \beta β

② 若 A   ∈   β A{\,}{\in}{\,}\beta Aβ ,则计算 α + {\alpha}^+ α+ ,但不使用 α → β \alpha\to\beta αβ,而用 α → ( β − A ) \alpha\to(\beta-A) α(βA) 代替,看看最后包不包括 A A A ,若包括则无关;(说明 α \alpha α 依据其他函数依赖就可以推出 A A A 来了,这里不需要再写一遍)

例 1:在函数依赖集 F = { A → C , A B → C } F=\{A{\to}C,AB{\to}C\} F={AC,ABC} 中,属性 B B B 对于 A B → C AB{\to}C ABC 来说是无关的,可以直接 A → C A{\to}C AC

例 2:在函数依赖集 F = { A → C , A B → C D } F=\{A{\to}C,AB{\to}CD\} F={AC,ABCD} 中,属性 C C C 对于 A B → C D AB{\to}CD ABCD 来说是无关的,可以直接 A B → D AB{\to}D ABD

(无关属性总是会出现在箭头的左边或右边,不可能不出现的哈,别理解错了)

Def:函数依赖集 F F F正则覆盖Canonical Cover),为等价于 F F F 的最小的函数依赖集,记为 F c F_c Fc

算法:同上述求无关属性算法的两种分类,遍历 F F F 中的每一条函数依赖 α → β \alpha\to\beta αβ

① 若 A ∈ α A{\in}\alpha Aα A A A 对于 α → β \alpha\to\beta αβ 是无关属性,则去掉 F F F 中的 α → β \alpha\to\beta αβ ,用 ( α − A ) → β (\alpha-A)\to\beta (αA)β 代替;

② 若 A ∈ β A{\in}\beta Aβ A A A 对于 α → β \alpha\to\beta αβ 是无关属性,则去掉 F F F 中的 α → β \alpha\to\beta αβ ,用 α → ( β − A ) \alpha\to(\beta-A) α(βA) 代替;

③ 去除所有无关属性后,若出现 α → β 1 \alpha\to\beta_1 αβ1 α → β 2 \alpha\to\beta_2 αβ2 ,则用 α → ( β 1 ∪ β 2 ) \alpha\to(\beta_1 \cup \beta_2) α(β1β2) 代替这两条函数依赖

特点

  • 所有函数依赖都不含无关属性
  • F c F_c Fc 中每条函数依赖的左部是唯一的,即不存在 α 1 → β 1 {\alpha}_1{\to}{\beta}_1 α1β1 α 1 → β 1 {\alpha}_1{\to}{\beta}_1 α1β1 α 1 = α 2 {\alpha}_1={\alpha}_2 α1=α2

(所以转化为正则覆盖的本质是合并相同的左部,去掉无关属性)

R = ( A , B , C ) R=(A,B,C) R=(A,B,C) F = { A → B C ,   B → C ,   A → B ,   A B → C } F=\{A{\to}BC,{\,}B{\to}C,{\,}A{\to}B,{\,}AB{\to}C\} F={ABC,BC,AB,ABC}

F c = { A → B ,   B → C } F_c=\{A{\to}B,{\,}B{\to}C\} Fc={AB,BC}

(极小函数依赖集的算法和正则覆盖使用去除无关属性的算法本质上是一样的,只是表述不同,尤其是在于正则表达式的左部要合并,而极小函数依赖集的右部要拆开)

无损分解

Def:将关系模式 R R R 分解为 R 1 R_1 R1 R 2 R_2 R2 时没有信息损失,则称为 无损分解Lossless-join Decomposition

要求:对于 R R R 中的所有实例 r r r ,都有 r = r 1    n a t r u a l   j o i n    r 2 r=r_1{\,}{\,}natrual{\,}join{\,}{\,}r_2 r=r1natrualjoinr2

db-10

充分条件:以下依赖至少有一个在 F + F^+ F+ 中:

  • R 1 ∩ R 2 → R 1 R_1{\cap}R_2{\to}R_1 R1R2R1
  • R 1 ∩ R 2 → R 2 R_1{\cap}R_2{\to}R_2 R1R2R2

上述只是充分条件,当作用在关系模式 R R R 上的所有约束都是函数依赖时,上述条件就是必要条件

(也就是说上述条件只能确保函数依赖的信息不被丢失,至于其他的信息就不一定了hhh)

保持依赖

Def:将 R R R 分解为 R 1 , R 2 , . . . , R n R_1,R_2,...,R_n R1,R2,...,Rn ,函数依赖集 F F F R i R_i Ri 上的限定 F + F^+ F+ 中所有只包含 R i R_i Ri 中属性的函数依赖集合 F i F_i Fi

Def:将 R R R 分解为 R 1 , R 2 , . . . , R n R_1,R_2,...,R_n R1,R2,...,Rn ,若所有限定有 ( F 1 ∪ F 2 ∪ . . . ∪ F n ) + = F + (F_1{\cup}F_2{\cup}...{\cup}F_n)^+=F^+ (F1F2...Fn)+=F+ ,则称该分解为 保持依赖dependency preserving) 的分解

算法 1:朴素算法,先计算 F + F^+ F+ ,再计算 ( F 1 ∪ F 2 ∪ . . . ∪ F n ) + (F_1{\cup}F_2{\cup}...{\cup}F_n)^+ (F1F2...Fn)+ ,最后比较二者是否相等(因为要计算 F + F^+ F+ ,所以开销很大)

算法 2:验证充分性:若 F F F 中每个函数依赖都可以在某个子关系 R i R_i Ri 上得到验证,那么显然是个保持依赖的分解

:关系模式 R = ( A , B , C ) R=(A,B,C) R=(A,B,C) ,函数依赖集 F = A → B , B → C F={A{\to}B,B{\to}C} F=AB,BC

R 1 = ( A , B ) R_1=(A,B) R1=(A,B) R 2 = ( B , C ) R_2=(B,C) R2=(B,C) 就是一个保持依赖的分解,可以用算法2验证;

注意:无损分解强调对于每一个具体的关系实例,拆分以后再自然连接可以得到原来的关系实例;保持依赖强调对于拆分以后的关系模式,仍然可以推导出原来的所有函数依赖;一个是实例层面的要求,一个是理论上的要求;

8.5 函数依赖的算法(Algorithms for Functional Dependencies)

BCNF分解

判断一个关系 R 是否属于 BCNF

算法:遍历 F F F 中所有 α → β \alpha{\to}\beta αβ,计算 α + {\alpha}^+ α+ ,若包含所有的属性,则满足条件;若有一个不包含,则不属于 B C N F BCNF BCNF

注意:如果 F F F 中没有函数依赖违反 B C N F BCNF BCNF,则 F + F^+ F+ 中也不会由函数依赖违反 B C N F BCNF BCNF ,所以只需对 F F F 中和的函数依赖进行检查;但判断 R R R 的一个分解 R i R_i Ri 是否属于 B C N F BCNF BCNF ,只用 F F F 就不够了

反例 R = ( A , B , C , D , E ) R=(A,B,C,D,E) R=(A,B,C,D,E) F = A → B ,   B C → D F={A\to B,{\,}BC\to D} F=AB,BCD ;若将 R R R 分解为 R 1 = ( A , B ) R_1=(A,B) R1=(A,B) R 2 = ( A , C , D , E ) R_2=(A,C,D,E) R2=(A,C,D,E) ,则用这里的算法,会误认为 R 2 R_2 R2 满足 B C N F BCNF BCNF

事实上, A C → D ∈   F + AC\to D {\in}{\,}F^+ ACDF+ ,所以 R 2 R_2 R2 是不满足 B C N F BCNF BCNF

注意 B C N F BCNF BCNF 的要求非常简单,就是所有非平凡函数依赖的左部都是超码

判断一个关系分解后是否属于BCNF

算法:对分解后的 R i R_i Ri 中属性的每个属性子集 α \alpha α,确保 α \alpha α 在原来 R R R 的函数依赖集 F F F 下的闭包 α + \alpha^+ α+ 要么不包含 R i − α R_i-\alpha Riα 的属性,要么包含 R i R_i Ri 中的所有属性

注意:如果违反了上面的条件,可以得到 α → ( α + − α ) ∩ R i ∈ F + \alpha\to(\alpha^+-\alpha){\cap}R_i{\in}F^+ α(α+α)RiF+ ,则违反了 B C N F BCNF BCNF

(因为这个时候意味着 α + \alpha^+ α+ 并不包含 R i R_i Ri 中的所有元素,即 α \alpha α 不能作为 R i R_i Ri 的超码;但却出现了 α \alpha α 在左部的函数依赖,与 B C N F BCNF BCNFDef 2 矛盾)

BCNF分解算法

以下算法可以分解一般的关系模式 R R R 并保证最终为 B C N F BCNF BCNF 范式:

① 计算 F + F^+ F+

② 遍历每一个不属于 B C N F BCNF BCNF R i R_i Ri,若有:

  • α   ∈   R i \alpha{\,}{\in}{\,}R_i αRi

  • α → β \alpha\to\beta αβ R i R_i Ri 上成立

  • α ∩ β = ∅ \alpha\cap\beta=\varnothing αβ=

    则用 R i − β R_i-\beta Riβ ( α , β ) (\alpha,\beta) (α,β) 替换掉原来的 R i R_i Ri

注意:我们在判定某个 R i R_i Ri 不属于 B C N F BCNF BCNF 的时候就已经得到 α \alpha α 了,相当于我们是在用违反 B C N F BCNF BCNF 的依赖在进行分解

R = ( A , B , C ) R=(A,B,C) R=(A,B,C) F = { A → B ,   B → C } F=\{A\to B,{\,}B{\to}C\} F={AB,BC}

则显然 A A A 是码,但还存在 B → C B\to C BC,于是可以分解为 ( A , B ) (A,B) (A,B) ( B , C ) (B,C) (B,C)

反例 R = ( J , K , L ) R=(J,K,L) R=(J,K,L) F = { J K → L ,   L → K } F=\{JK\to L,{\,}L{\to}K\} F={JKL,LK} R R R 不是 B C N F BCNF BCNF ,但是任何分解都不能保证 J K → L JK\to L JKL

(虽然总是可以无损分解(除函数依赖外)为 B C N F BCNF BCNF ,但是函数依赖无法总是保留

(这样的反例启示我们,有时候并不能分解为 B C N F BCNF BCNF ,引出了下面的 3 N F 3NF 3NF 分解)

db-8-2

3NF分解

(上面的反例说明,有时候我们需要保留一些冗余,来分解为无损分解、保持依赖的 3 N F 3NF 3NF (上面的 ( l 1 , k 1 ) (l_1,k_1) (l1,k1) 就是在重复))

判断一个关系 R 是否属于 3NF

算法:遍历 F F F 中的每个函数依赖 α → β \alpha \to \beta αβ

  • 计算 α + \alpha^+ α+ ,若包含 R R R 的所有属性,即为超码,则符合条件
  • 否则,遍历 β \beta β 中的每个属性,判断是否都包含于某个候选码中;若是,则符合条件;

(算法的原理在于,第三范式已经解决了非主属性传递依赖于码的问题,但是还没有解决主属性之间的依赖问题;因此若 α \alpha α 不是超码,则 β \beta β 应该是主属性的集合)

(只要遍历 F F F 中的函数依赖就可,不用计算 F + F^+ F+

(由于要计算候选码,因此判定非常复杂,应该是个NP问题;但是分解为 3 N F 3NF 3NF 却是P类问题)

3NF 分解算法

以下算法可以对一般关系模式 R R R 在保持依赖的情况下无损分解为 3 N F 3NF 3NF

① 计算 F c F_c Fc

② 遍历 F c F_c Fc 中每一条函数依赖 α → β \alpha \to \beta αβ ,组合成 α β \alpha \beta αβ 作为 R i R_i Ri 加入;

③ 若没有一个 R i R_i Ri 包含原来 R R R 的任一候选码,则任意选 R R R 的一个候选码作为一个新的 R i R_i Ri 加入;

④ 除冗:若有某个关系模式 R j R_j Rj 包含于 R i R_i Ri ,则删除 R j R_j Rj ;最后丢弃原来的 R R R,将所有 R i R_i Ri 作为分解结果;

注意:总是可以将任意关系模式保持依赖、无损分解为第三范式!!!

:设关系模式 R = R= R=(账号,储蓄额,收储员,储蓄所名),有函数依赖 F = F= F= { \{ {

  • (账号,收储员) → \to (储蓄额,储蓄所名)
  • 收储员 → \to 储蓄所名
  • (账号,储蓄所名) → \to 收储员 } \} }

(这里假定某个客户在某家银行的负责人,即收储员是唯一的,多对一)

(账号,收储员) 可作为候选码,但是有 储蓄所名 依赖于 收储员 间接依赖于这个候选码,因此不是第三范式

计算得到 F c = { F_c=\{ Fc={

  • (账号,收储员) → \to 储蓄额
  • 收储员 → \to 储蓄所名
  • (账号,储蓄所名) → \to 收储员 } \} }

依据上边的算法,可拆分为两张子表:(账号,收储员,储蓄额) 和 (账号,储蓄所名,收储员)

8.6 多值依赖(Multivalued Dependencies )

(函数依赖只能表示事物之间、事物属性之间一对一或一对多的联系,但还需要多值依赖来表示某事物(或事物属性)与其他多个事物(或事物属性)的相关关系)

Def 像集:设 R ( U ) R(U) R(U) 是一个关系, X , Y ∈ U X, Y{\in}U X,YU;对于 R R R 的元组中的每一个 X X X 的值 x x x ,都存在着某个 Y Y Y 值的集合与之相关联,我们称这个 Y Y Y 值的集合为 R R R x x x Y Y Y 像集,记作 Y U ( x ) Y_U(x) YU(x) ,即 Y U ( x ) = { t [ Y ]   ∣   t ∈ R Y_U(x)=\{t[Y] {\,}|{\,}t{\in}R YU(x)={t[Y]tR t [ X ] = x } t[X]=x\} t[X]=x}

(就比如 X X X 是教职工, Y Y Y 是电话号码,一个教职工有多个电话号码,但一个电话号码只能属于一个教职工)

多值依赖的定义

(多值依赖就是某个属性集合的一个值对应的像集有多个值的关联关系)

Def 1:设 R ( U ) R(U) R(U) 是一个关系模式, X , Y   ∈   U X, Y{\,}{\in}{\,}U X,YU Z = U − X Y Z=U-XY Z=UXY,关系模式 R R R 上的一个多值依赖是形如 g : X → → Y g:X\to \to Y g:XY 的一个命题,它的含义是:对于 R R R 的任一可能的实例关系中的元组的每一个 X Z XZ XZ 的值 x z xz xz ,都有 Y U ( x z ) = Y U ( x ) Y_U(xz)=Y_U(x) YU(xz)=YU(x) ,即对于每一个给定的 X Z XZ XZ-值,其 Y Y Y-像集的值都仅仅依赖于 X Z XZ XZ-值的 X X X 分量,而与 Z Z Z 分量毫无关系。称在 R R R X X X 多值决定 Y Y Y ,或 Y Y Y 多值依赖于 X X X

Def 2:设 R ( U ) R(U) R(U) 是一个关系模式, X , Y   ∈   U X, Y{\,}{\in}{\,}U X,YU Z = U − X Y Z=U-XY Z=UXY,关系模式 R R R 上的一个多值依赖是形如 g : X → → Y g:X\to \to Y g:XY 的一个命题,它的含义是:对于 R R R 的任一可能的实例关系 r r r ,如果存在元组 t , s   ∈   r t,s{\,}{\in}{\,}r t,sr,使得 t [ X ] = s [ X ] t[X]=s[X] t[X]=s[X] ,则必定存在元组 u   ∈   r u{\,}{\in}{\,}r ur,使得 u [ X ] = t [ X ] = s [ X ] u[X]=t[X]=s[X] u[X]=t[X]=s[X] ,而 u [ Y ] = t [ Y ] u[Y]=t[Y] u[Y]=t[Y] u [ Z ] = s [ Z ] u[Z]=s[Z] u[Z]=s[Z]

(这个很,太抽象了,赶紧先看个例子: ↓ \downarrow

i n s t _ i n f o   ( I D , c h i l d _ n a m e , p h o n e _ n u m b e r ) inst\_info{\,}(ID, child\_name, phone\_number) inst_info(ID,child_name,phone_number)

IDchild_namephone_number
99999David512-555-1234
99999David512-555-4321
99999William512-555-1234
99999William512-555-4321

有: I D → → c h i l d _ n a m e ID\to\to child\_name IDchild_name I D → → p h o n e _ n u m b e r ID\to\to phone\_number IDphone_number ,即 c h i l d _ n a m e child\_name child_name 属性和 p h o n e _ n u m b e r phone\_number phone_number 属性分别于 I D ID ID 属性多值相关,但二者无关;

引理 R ( U ) R(U) R(U) 是个关系模式:

  • X → → Y X\to \to Y XY 当且仅当 X → → U − X Y X\to \to U-XY XUXY
  • Y ′ = Y − X Y'=Y-X Y=YX ,则 X → → Y X\to \to Y XY 当且仅当 X → → Y ’ X\to \to Y’ XY
  • Y   ⊆   X   ⊆   U Y{\,}{\subseteq}{\,}X{\,}{\subseteq}{\,}U YXU ,则 X → → Y X\to \to Y XY
  • U = X Y U=XY U=XY ,则 X → → Y X\to \to Y XY
函数依赖与多值依赖的关系

① 函数依赖可以被看做是多值依赖的一个子类

② 重要区别:

  • 函数依赖定义, X → Y X\to Y XY是否成立仅与 X Y XY XY 的值有关,不受其他属性值的影响
  • 多值依赖 X → → Y X\to \to Y XY 是否成立,不仅要考察 X Y XY XY 的值,而且要考察 U − X Y U-XY UXY 的值;即,讨论任何一个 X → → Y X\to \to Y XY 不能离开它的论域,论域变化, X → → Y X\to \to Y XY 满足性就要改变

(多值依赖考虑的比较多,例如 R ( R( R(班级,学员,课程 ) ) ),则班级 → → \to \to 学员,班级 → → \to \to 课程;如果扩展该模式, R ′ ( R'( R(班级,学员,课程,成绩 ) ) ),则上述两个多值依赖都不再成立。论域变化,属性值之间关系不再满足多值依赖的定义。)

注意:若 Y → Z Y\to Z YZ,则 Y → → Z Y\to \to Z YZ

性质

Th:设 r r r 是关系模式 R ( U ) R(U) R(U) 的一个实例关系, X , Y   ∈   U X, Y{\,}{\in}{\,}U X,YU Z = U − X Y Z=U-XY Z=UXY ,则关系 r r r 满足MVD X → → Y X\to \to Y XY 当且仅当 r r r 可以联接无损地分解到两个关系模式 R 1 = X Y R1 =XY R1=XY R 2 = X Z R2 =XZ R2=XZ

检验方法:检验某个关系 r r r 是否满足多值依赖 X → → Y X\to \to Y XY :把 r r r 投影到 X Y XY XY X Z XZ XZ Z Z Z 就是上面的补集)上,然后对投影做自然连接;若结果还是 r r r (即无损连接),则有 X → → Y X\to \to Y XY ,否则不成立;

(比如上边那个例子,分解为 ( I D , c h i l d _ n a m e ) (ID,child\_name) (ID,child_name) ( I D , p h o n e _ n u m b e r ) (ID,phone\_number) (ID,phone_number) ,再连接起来还是原来的表,说明多值依赖成立 )

多值依赖推导公理:(单一的MVD环境)设 R ( U ) R(U) R(U) 是一个关系模式, X , Y , W , Z ∈ U X, Y, W, Z{\in}U X,Y,W,ZU,则

  • MVD0(补规则) X → → Y X\to \to Y XY ,则 X → → U − X Y X\to \to U-XY XUXY
  • MVD1(自反公理)若 Y   ⊆   X   ⊆   U Y{\,}{\subseteq}{\,}X{\,}{\subseteq}{\,}U YXU ,则 X → → Y X\to \to Y XY
  • MVD2(增广规则)若 V ⊆ W V{\subseteq}W VW X → → Y X\to \to Y XY ,则 X W → → Y V XW\to \to YV XWYV
  • MVD3(传递规则)若 X → → Y X\to \to Y XY Y → → Z Y\to \to Z YZ,则 X → → Z X\to \to Z XZ
  • MVD4(并规则)若 X → → Y X\to \to Y XY X → → Z X\to \to Z XZ,则 X → → Y Z X\to \to YZ XYZ
  • MVD5(投影规则)若 X → → Y X\to \to Y XY X → → Z X\to \to Z XZ,则 X → → Y ∩ Z X\to \to Y{\cap}Z XYZ
  • MVD6(伪传递规则)若 X → → Y X\to \to Y XY W Y → → Z WY\to \to Z WYZ,则 X W → → Z − Y W XW\to \to Z-YW XWZYW

(MVD 0、1、3 就可以推出其他公式)

第四范式
定义

Def 平凡多值依赖:若 β   ⊆   α \beta{\,}{\subseteq}{\,}\alpha βα 或者 β   ∪ α = R {\beta}{\,}{\cup}{\alpha}=R βα=R ,则称 α → → β \alpha \to \to \beta αβ 称为平凡的多值依赖

Def:设 R R R 是一个关系模式,如果对于在 R R R 上成立的每一个非平凡 M V D MVD MVD X → → Y X\to \to Y XY X X X 都是 R R R 的一个超码,则称 R R R 是属于第四范式的,记作 R   ∈   4 N F R{\,}{\in}{\,}4NF R4NF

Def 闭包:(闭包的扩展定义) D D D 是函数依赖和多值依赖的集合, D D D闭包 D + D^+ D+ 是由 D D D 逻辑蕴涵的所有函数依赖和多值依赖的集合

Def D D D R i R_i Ri 上的限定集合 D i D_i Di 定义为:

  • D + D^+ D+ 中所有只含 R i R_i Ri 中属性的函数依赖;
  • 所有形如 α → → ( β ∩ R i ) \alpha \to \to (\beta{\cap}R_i) α(βRi) 的多值依赖,其中 α ⊆ R i \alpha{\subseteq}R_i αRi α → → β   ⊆   D + \alpha \to \to \beta {\,}{\subseteq}{\,}D^+ αβD+

注意:第四范式一定属于 B C N F BCNF BCNF

第四范式分解

以下算法可以无损分解为 4 N F 4NF 4NF

① 计算 D + D^+ D+

② 对每一个不属于第四范式的子关系模式 R i R_i Ri,令 α → → β \alpha \to \to \beta αβ 为在 R i R_i Ri 上成立的非平凡多值依赖,使得 α → R i \alpha \to R_i αRi 不属于 D i D_i Di ,且 α   ∩   β = ∅ \alpha {\,}{\cap}{\,} \beta=\varnothing αβ= ,则使用 R i − β R_i- \beta Riβ ( α ,   β ) (\alpha,{\,}\beta) (α,β) 代替 R i R_i Ri

db-4

(我实在不想打字了,原谅我吧~现在已经了,该去洗澡啦~)

db-9

(第五范式不太常用,其实最重要的是 B C N F BCNF BCNF 和第三范式!)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Air浩瀚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值