验证非键列依赖和传递依赖

Verifying non-key column dependencies and transitive dependencies

我正在设计我的第一个数据库,我正在尝试遵循高达 3NF 的规范化规则。我使用以下定义进行规范化:

table用于存储宠物食品的信息。这是任何规范化之前 table 的基本示例:

╔════════════╦═════════╦═════════════╦════════════╦═══════════╦═══════════════╦═══════╗
║ Brand      ║ Flavor  ║ Animal Type ║ Breed Size ║ Age Group ║ Ingredients   ║ Price ║
╠════════════╬═════════╬═════════════╬════════════╬═══════════╬═══════════════╬═══════╣
║ Purina     ║ Chicken ║ Dog         ║ Small      ║ Adult     ║ Chicken, Salt ║ 18.99 ║
╠════════════╬═════════╬═════════════╬════════════╬═══════════╬═══════════════╬═══════╣
║ BlueWilder ║ Chicken ║ Dog         ║ Small      ║ Adult     ║ Chicken, Salt ║ 18.99 ║
╚════════════╩═════════╩═════════════╩════════════╩═══════════╩═══════════════╩═══════╝

按照上面的1NF定义,我添加了一个主键列。在这种情况下,唯一的问题是每条记录包含多个条目的成分列:

╔═════════╦════════════╦═════════╦═════════════╦════════════╦═══════════╦═════════════╦═══════╗
║ Food ID ║ Brand      ║ Flavor  ║ Animal Type ║ Breed Size ║ Age Group ║ Ingredients ║ Price ║
╠═════════╬════════════╬═════════╬═════════════╬════════════╬═══════════╬═════════════╬═══════╣
║ 1       ║ Purina     ║ Chicken ║ Dog         ║ Small      ║ Adult     ║ Chicken     ║ 18.99 ║
╠═════════╬════════════╬═════════╬═════════════╬════════════╬═══════════╬═════════════╬═══════╣
║ 1       ║ Purina     ║ Chicken ║ Dog         ║ Small      ║ Adult     ║ Salt        ║ 18.99 ║
╠═════════╬════════════╬═════════╬═════════════╬════════════╬═══════════╬═════════════╬═══════╣
║ 2       ║ BlueWilder ║ Chicken ║ Dog         ║ Small      ║ Adult     ║ Chicken     ║ 18.99 ║
╠═════════╬════════════╬═════════╬═════════════╬════════════╬═══════════╬═════════════╬═══════╣
║ 2       ║ BlueWilder ║ Chicken ║ Dog         ║ Small      ║ Adult     ║ Salt        ║ 18.99 ║
╚═════════╩════════════╩═════════╩═════════════╩════════════╩═══════════╩═════════════╩═══════╝

由于成分列,现在有一个重复组。为了解决这个问题,我创建了两个单独的 table;成分 table,以及将成分 table 和食物 table 连接在一起的关联词 table:

╔═══════════════╦════════════╗
║ Ingredient ID ║ Ingredient ║
╠═══════════════╬════════════╣
║ 1             ║ Chicken    ║
╠═══════════════╬════════════╣
║ 2             ║ Salt       ║
╚═══════════════╩════════════╝

╔═════════╦═══════════════╗
║ Food ID ║ Ingredient ID ║
╠═════════╬═══════════════╣
║ 1       ║ 1             ║
╠═════════╬═══════════════╣
║ 1       ║ 2             ║
╠═════════╬═══════════════╣
║ 2       ║ 1             ║
╠═════════╬═══════════════╣
║ 2       ║ 2             ║
╚═════════╩═══════════════╝

现在,我可以从食物中删除成分列 table:

╔═════════╦════════════╦═════════╦═════════════╦════════════╦═══════════╦═══════╗
║ Food ID ║ Brand      ║ Flavor  ║ Animal Type ║ Breed Size ║ Age Group ║ Price ║
╠═════════╬════════════╬═════════╬═════════════╬════════════╬═══════════╬═══════╣
║ 1       ║ Purina     ║ Chicken ║ Dog         ║ Small      ║ Adult     ║ 18.99 ║
╠═════════╬════════════╬═════════╬═════════════╬════════════╬═══════════╬═══════╣
║ 2       ║ BlueWilder ║ Chicken ║ Dog         ║ Small      ║ Adult     ║ 18.99 ║
╚═════════╩════════════╩═════════╩═════════════╩════════════╩═══════════╩═══════╝

此时,我不确定如何进行。

我的思路是这样的:如果任何非主键列的值发生变化,那么Food ID一定是不同的。例如,品牌、风味、品种大小、年龄段、成分和价格都可以相同。但是如果动物类型是狗,然后变成猫,那肯定是不同的记录。这适用于所有非主键列。按照这种思路,所有非主键列都完全依赖于主键,不存在传递依赖。

我的思路对吗?根据我上面列出的定义,2NF 和 3NF 是否已经满足?

要在屏幕上保存 space 我将重命名属性:

  • 品牌:BRD
  • 风味:FLA
  • 动物:ANM
  • 品种规格:SIZ
  • 年龄段:AGP
  • 成分:ING
  • 价格:PRI

方法一

规范化,如教科书所述。

步骤 1.1

由于 ingredients 中的重复组,table 中的值不是关系,因此 table 不代表关系变量,因此在 1NF 中它是 not。解决方案是确保 ingredient 列 (ING) 每行 exactly one 成分——正如您所做的那样。但是,没有添加新属性(没有新 ID)。现在我们有(在 1NF 中):

R {BRD, FLA, ANM, SIZ, AGP, ING, PRI}

整个标题是关键。

步骤 1.2

来自 FDs:

  • {BRD, FLA} -> {ANM}
  • {BRD, FLA} -> {SIZ}
  • {BRD, FLA} -> {AGP}
  • {BRD, FLA} -> {PRI}

通过对 FD 和 Heath 定理应用并集规则:

 R1 {BRD, FLA, ANM, SIZ, AGP, PRI}
KEY {BRD, FLA}

 R2 {BRD, FLA, ING}
KEY {BRD, FLA, ING}

完成。就是这样,如果我得到 FDs 正确的话。
两者都在 BCNF 中,我有信心说 R1 在 5NF 中,R2 在 6NF 中。

方法二

Database design is predicate design.

不是大多数教科书中的正式归一化方法,而是设计方法导致tables处于高NF(5NF,6NF)。

第一步,使用简单谓词和相关约束来描述问题(业务领域)。然后可以使用逻辑自然语言推理问题。

一个简单的谓词不能在不丢失信息的情况下分解,它的匹配relvar在6NF.

在第二步中,可以将这些简单谓词(和匹配的关系变量)组合起来,确保不引入冗余和逻辑错误的可能性,即矛盾。完成后,relvars (tables) 预计将在 5NF 中。

步骤 2.1

使用简单谓词描述问题并匹配 6NF 关系变量。不表达约束(它得到 long-winded),只是陈述它们。

-- Brand BRD exists.
--
brand {BRD}
   PK {BRD}
-- Flavor FLA exists.
--
flavor {FLA}
    PK {FLA}
-- Animal type ANM exists.
--
animal {ANM}
    PK {ANM}
-- Breed size SIZ exists.
--
bsize {SIZ}
   PK {SIZ}
-- Age group AGP exists.
--
age {AGP}
 PK {AGP}
-- Ingredient ING exists.
--
ingredient {ING}
        PK {ING}
-- Pet food with flavor FLA made by brand BRD
-- is for animal type ANM.
--
food {BRD, FLA, ANM}
  PK {BRD, FLA}

 FK1 {BRD} REFERENCES brand  {BRD}
 FK2 {FLA} REFERENCES flavor {FLA}
 FK3 {ANM} REFERENCES animal {ANM}
-- Pet food with flavor FLA made by brand BRD
-- is recommended for breed size SIZ.
--
food_bsize {BRD, FLA, SIZ}
        PK {BRD, FLA}

       FK1 {BRD, FLA} REFERENCES
      food {BRD, FLA}

       FK2 {SIZ} REFERENCES bsize {SIZ}
-- Pet food with flavor FLA made by brand BRD
-- is recommended for breed age group AGP.
--
food_age {BRD, FLA, AGP}
      PK {BRD, FLA}

       FK1 {BRD, FLA} REFERENCES
      food {BRD, FLA}

       FK2 {AGP} REFERENCES age {AGP}
-- Pet food with flavor FLA made by brand BRD
-- is priced at PRI Euros per unit.
--
price {BRD, FLA, PRI}
   PK {BRD, FLA}

   FK {BRD, FLA} REFERENCES
 food {BRD, FLA}
-- Pet food with flavor FLA made by brand BRD
-- contains ingredient ING.
--
recipe {BRD, FLA, ING}
    PK {BRD, FLA, ING}

   FK1 {BRD, FLA} REFERENCES
  food {BRD, FLA}

   FK2 {ING} REFERENCES ingredient {ING}

步骤 2.2

只看键位,我们可以看到food, food_bsize, food_age价格table可以合并

-- Pet food with flavor FLA made by brand BRD
-- is for animal type ANM, recommended for
-- breed size SIZ, breed age group AGP; priced
-- at PRI Euros per unit.
--
food_ {BRD, FLA, ANM, SIZ, AGP, PRI}
   PK {BRD, FLA}

 FK1 {BRD} REFERENCES brand  {BRD}
 FK2 {FLA} REFERENCES flavor {FLA}
 FK3 {ANM} REFERENCES animal {ANM}
 FK4 {SIZ} REFERENCES bsize  {SIZ}
 FK5 {AGP} REFERENCES age    {AGP}

如果我们决定保留前六个table定义域,那么最终结果与第一种方法一样:

food_ {BRD, FLA, ANM, SIZ, AGP, PRI}
   PK {BRD, FLA}


recipe {BRD, FLA, ING}
    PK {BRD, FLA, ING}

    FK {BRD, FLA} REFERENCES food_
       {BRD, FLA}

但是,在 real-world 项目中,您可能需要 brandflavoranimal bsizeage tables 来约束域。规范化中没有规定你应该拥有它们。
此外,并非所有属性都同时已知,因此您不太可能将所有 foodfood_bsizefood_age价格 tables 到 food_。这将取决于业务流程和属性的可选性。

添加 ID

添加代理键 (ID) 与规范化无关。您可能出于其他原因需要添加它们,请查看 this example.


注:

All attributes (columns) NOT NULL

KEY = PK or AK

PK = Primary Key
AK = Alternate Key   (Unique)
SK = Proper Superkey (Unique)
FK = Foreign Key

我一直用第二种方法来设计。从未见过第一个在某种正式的数据库课程之外使用的;以及寻求有关 SO 帮助的人。 出于某种原因,超出我的理解,方法 1 方法 2 之前在主题为“数据库设计”的数据库课程中教授。大多数学校根本不教方法2。去图吧。