【问题标题】:Normalising a database to reduce dependency规范化数据库以减少依赖性
【发布时间】:2016-06-24 19:33:47
【问题描述】:

我正在努力使我的数据库设计正确。它是由啤酒、白酒、葡萄酒等组成的一大组酒精饮料。我可以将它们全部保存在一个表中,如下所示:

id category brand     type    price  quantity  description  

1  Beer     Heineken  bottle  $2.00  100       some description...
2  Beer     Calsburg  bottle  $3.00  200       some description
3  Beer     Heineken  can     $1.00  300       some description....
4  Liquor   JWalker   bottle  $30.00 100       some descri...

考虑到类别和品牌会出现重复,这似乎是一个糟糕的设计。因此,我将其拆分为 3 个表,如下所示:

分类表

id   name(pk)

1    Beer
2    Liquor

品牌表

id   name(pk)    category_name(FK)
1    Heineken    Beer
2    Carlsburg   Beer
3    Lindemans   Wine
4    JWalker     Liquor

产品表

id(PK)     type    price    quantity    description       category_name(FK) brand_name(FK)
1          Bottle  $2.00    100         some description  Beer              Heineken

认为这会更好地标准化,但在我看来,与第一个表几乎没有区别。我也以重复类型结束,因为我可以在瓶子上重复,罐头等等。那么我应该为此获得第四张桌子吗?

尝试正常化并使其尽可能合理。有没有更好的方法来做到这一点?

【问题讨论】:

  • 我认为如果它们始终是唯一的,那么将名称用作 PK 是可以的,但是,正如 OP 指出的那样......由于没有与品牌或类别相关的额外数据,拆分并没有太大优势离开桌子。
  • 说喜力被另一家公司买断/出售和/或重新命名。您想更新所有产品还是只更新品牌表中的一条记录?单个表可能很诱人,但从长远来看会降低灵活性(可能不是减少而是增加返工)。您是否计划让这个系统不断变化?如果是这样,请尽可能接近 3rd/4th。 如果这就是它的全部内容并且您没有预料到变化,那么单个表将“更快”,只是维护更加困难。
  • 所以成本效益,现在快速简单,以后更痛苦。或者现在稍微痛苦一点,以便以后减少痛苦/返工。你现在有时间愿意承受更多的痛苦吗?如果没有,请快速轻松并稍后更正。但是,如果现在有很多代码违背了这种结构,那么现在就编写代码,否则以后会有很多返工..
  • @xQbert 添加 ids 与规范化无关。
  • 接受的答案没有标准化。规范化不会引入新列。您没有提供足够的信息来规范化;但根据常识和列名,您的第一个表在 5NF 中。您似乎认为重复的子行值意味着需要规范化。他们没有。 (请参阅我的回答。)请提供您的表中保存的 FD,以及始终是其他表连接的任何其他情况。请说当一行(id,...)进入您的 tab.e 时。 PS你能清楚地解释一下“类别和品牌的重复”是什么意思吗?

标签: mysql oracle database-normalization


【解决方案1】:
Brand Table
brandID(PK) BrandName

Category table
BrandID(FK) CategoryID(PK) Categoryname

Product table
ProductID(PK) CategoryID(FK) description price quantity

【讨论】:

  • 类别不需要与品牌相关,BrandID作为外键属于产品。
【解决方案2】:

规范化需要知道函数依赖 (FD) 和连接依赖 (JD)。你没有给他们。所以我们不能正常化。但猜测您的应用程序和您的表,它属于 5NF。

大概 id 是一个唯一的列。因此它在功能上确定了每个列集。由于没有更小的 {id} 子集是唯一的,因此它是候选键 (CK)。大概没有其他 FD 持有,除了那些因为那个 CK 而持有的 FD。所以该表在 5NF 中。

但假设还有一个 FD 成立:一个给定的品牌只出现在同一个类别中。然后为了规范化到 5NF 列,应该删除类别,并添加一个包含品牌和类别列以及 CK {brand} 的新表。

或者假设一个品牌有一个或多个类别,而不是一行表明该类别是其产品的类别,而是表明该类别是其产品品牌的一个类别。 (奇怪的是,从那以后,对于具有多个类别的品牌,该表不会给出产品的类别。)然后规范化也给出了这两个表,带有新的 CK {类别,品牌}。但在这种情况下,这是因为多值依赖(MVD),即因为二进制 JD。

PS 引入 ids 与规范化无关。

PPS 您似乎认为重复的子行值意味着需要标准化。他们没有。规范化有时用于将表替换为始终连接到该表的表。

【讨论】:

    【解决方案3】:

    通过 BCNF 进行标准化是基于函数依赖的。它不是基于列是否包含文本或数字。您似乎认为,由于类别列不止一次包含 Beer 一词,因此需要对其进行“规范化”。事实并非如此。

    那么这里的函数依赖是什么?

    • id -> 类别、品牌、类型、价格、数量、描述
    • 类别、品牌、类型、-> id、价格、数量、描述

    第二个 FD 可能是错误的。 {brand, type} 可能是决定因素。但我认为很可能有一家公司在同一品牌下生产啤酒和白酒。所以我认为决定因素可能是{类别、品牌、类型}。

    这已经在 5NF 中了。 “拆分”不会改善此表。

    【讨论】:

      【解决方案4】:

      表创建看起来像这样:

      create table product (
         product_id int not null identity,
         brand_id int not null,
         category_id int not null,
         primary key(product_id),
         foreign key brand_id references brand(brand_id),
         foreign key category_id references category(category_id)
      );
      
      create table brand (
          brand_id int not null identity,
          name varchar(80),
          primary key(brand_id)
      );
      
      create table category (
         category_id int int not null identity,
         name varchar(80),   
         primary key(category_id)
      );
      

      您执行 JOIN 以取回记录:

      select p.product_id, c.name as category_name, b.name as brand_name
      from product as p
      join category as c on p.category_id = c.category_id
      join brand as b on p.brand_id = b.brand_id
      

      【讨论】:

      • 问题是“尝试规范化并使其尽可能合理。有没有更好的方法来做到这一点?”。原始表在 5NF 中。问题的第二种设计不是归一化的产物。无论如何不可能,因为它引入了新列:ids。同上你的答案。可能想添加 id;但这不是标准化。 PS 如果您刚刚对我的答案投了反对票,请告诉我您认为错误的第一件事,我将添加参考以表明我的答案是正确的。或者只是阅读有关规范化的教科书或幻灯片(许多是在线的)。
      • 我希望你能试着找到一本与我写的任何东西都不一致的教科书。
      • @duffymo:“我没有添加任何新的列名。”brand_id 和 category_id 都不在原始表中。
      • “仅作为示例。将其视为替代” 关于数据库规范化,这只是一个错误。
      • @duffymo:我是说引入不在原始关系中的属性不是规范化的一部分。您介绍了两个:brand_id 和 category_id。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-28
      • 2012-03-08
      • 2012-01-06
      • 1970-01-01
      • 1970-01-01
      • 2022-06-25
      • 2015-08-08
      相关资源
      最近更新 更多