规范化数据库以减少依赖性

时间:2016-06-16 14:10:57

标签: mysql oracle database-normalization

我正在努力让我的数据库设计正确。这是一大套酒精饮料,包括啤酒,白酒,葡萄酒等。我可以将它们保存在一个表中,如下所示:

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

认为这会更好地规范化,但我看到它的方式,与第一张表几乎没有区别。我也以类型repeatnig结束,因为我可以重复瓶子,罐头等等。那我应该拿到第4张桌子吗?

尝试规范化并尽可能保持合理。有没有更好的方法来做这个?

4 个答案:

答案 0 :(得分:0)

Brand Table
brandID(PK) BrandName

Category table
BrandID(FK) CategoryID(PK) Categoryname

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

答案 1 :(得分:0)

规范化需要了解功能依赖(FD)和连接依赖(JD)。你没有给他们。所以我们无法正常化。但是猜测你的应用程序和你的桌子,它在5NF。

据推测,id是一个独特的列。因此它在功能上确定每个列集。由于{id}的较小子集不是唯一的,因此它是候选密钥(CK)。据推测,由于那个CK,其他FD不会持有其他FD。因此该表位于5NF。

但是假设还有一个FD持有:一个给定的品牌只出现在同一类别。然后要标准化为5NF列类别应该删除,并且应该添加一个新的表格,品牌和&类别列和CK {品牌}。

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

PS介绍ID与规范化无关。

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

答案 2 :(得分:-1)

通过BCNF进行规范化是基于功能依赖性。它不是基于列是包含文本还是数字。您似乎认为,因为类别列不止一次包含单词 Beer ,所以它需要“规范化”。事实并非如此。

那么这里的功能依赖是什么?

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

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

那已经是5NF了。 “拆分”不会改善此表。

答案 3 :(得分:-2)

表创建看起来像这样:

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