规范化数据库以减少依赖性
Normalising a database to reduce dependency
我正在努力使我的数据库设计正确。它是由啤酒、白酒、葡萄酒等组成的一大套酒类饮品。我可以将其全部保存在一个 table 中,如下所示:
id category brand type price quantity description
1 Beer Heineken bottle .00 100 some description...
2 Beer Calsburg bottle .00 200 some description
3 Beer Heineken can .00 300 some description....
4 Liquor JWalker bottle .00 100 some descri...
考虑到类别和品牌的重复,这似乎是一个糟糕的设计。因此我将它分成 3 tables 如下:
类别Table
id name(pk)
1 Beer
2 Liquor
品牌Table
id name(pk) category_name(FK)
1 Heineken Beer
2 Carlsburg Beer
3 Lindemans Wine
4 JWalker Liquor
产品Table
id(PK) type price quantity description category_name(FK) brand_name(FK)
1 Bottle .00 100 some description Beer Heineken
认为这会更好地规范化,但在我看来,与第一个 table 几乎没有区别。我也以类型 repeatnig 结尾,因为我可以在瓶子、罐头等上重复。那么我应该为此获得第 4 个 table 吗?
试图正常化并尽可能保持理智。有没有更好的方法去做这件事?
Brand Table
brandID(PK) BrandName
Category table
BrandID(FK) CategoryID(PK) Categoryname
Product table
ProductID(PK) CategoryID(FK) description price quantity
Table 创建看起来像这样:
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
规范化需要知道函数依赖关系 (FD) 和连接依赖关系 (JD)。你还没有给他们。所以我们不能正常化。但是猜测你的应用程序和你的 table,它是 5NF。
大概 id 是一个唯一的列。因此它在功能上确定了每个列集。由于 {id} 的较小子集不是唯一的,因此它是候选键 (CK)。据推测,除了因为那个 CK 而持有的 FD 之外,没有其他 FD 持有。所以 table 在 5NF 中。
但假设还有一个 FD 成立:给定品牌只出现在同一类别中。然后归一化为 5NF 列类别应该被删除,并且应该添加一个新的 table 与品牌 & 类别列和 CK {brand}。
或者假设一个品牌有一个或多个类别,而不是声明类别是其产品类别的行,而是声明类别是其产品品牌的类别。 (很奇怪,从那时起,对于具有多个类别的品牌,table 不会给出产品的类别。)然后归一化也会给出这两个 tables,以及新的 CK {category, brand}。但在这种情况下,这是因为多值依赖性 (MVD),即因为二进制 JD。
PS引入ids与规范化无关
PPS 您似乎认为重复的子行值意味着需要规范化。他们没有。规范化是为了有时用 table 替换 table,而 table 总是加入它。
通过 BCNF 的规范化基于函数依赖性。它不基于列是否包含文本或数字。您似乎认为,因为类别列不止一次包含单词 Beer,所以它需要是 "normalized"。事实并非如此。
那么这里的函数依赖是什么?
- id -> 类别、品牌、类型、价格、数量、描述 [=24=]
- 类别、品牌、类型 -> ID、价格、数量、描述 [=24=]
第二个 FD 可能是错误的。 {brand, type} 可能是决定因素。但我认为很可能某处有一家公司以同一品牌名称生产啤酒和白酒。所以我认为决定因素可能是{category, brand, type}。
那已经在 5NF 中了。 "Splitting" 不会改进这个 table。
我正在努力使我的数据库设计正确。它是由啤酒、白酒、葡萄酒等组成的一大套酒类饮品。我可以将其全部保存在一个 table 中,如下所示:
id category brand type price quantity description
1 Beer Heineken bottle .00 100 some description...
2 Beer Calsburg bottle .00 200 some description
3 Beer Heineken can .00 300 some description....
4 Liquor JWalker bottle .00 100 some descri...
考虑到类别和品牌的重复,这似乎是一个糟糕的设计。因此我将它分成 3 tables 如下:
类别Table
id name(pk)
1 Beer
2 Liquor
品牌Table
id name(pk) category_name(FK)
1 Heineken Beer
2 Carlsburg Beer
3 Lindemans Wine
4 JWalker Liquor
产品Table
id(PK) type price quantity description category_name(FK) brand_name(FK)
1 Bottle .00 100 some description Beer Heineken
认为这会更好地规范化,但在我看来,与第一个 table 几乎没有区别。我也以类型 repeatnig 结尾,因为我可以在瓶子、罐头等上重复。那么我应该为此获得第 4 个 table 吗?
试图正常化并尽可能保持理智。有没有更好的方法去做这件事?
Brand Table
brandID(PK) BrandName
Category table
BrandID(FK) CategoryID(PK) Categoryname
Product table
ProductID(PK) CategoryID(FK) description price quantity
Table 创建看起来像这样:
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
规范化需要知道函数依赖关系 (FD) 和连接依赖关系 (JD)。你还没有给他们。所以我们不能正常化。但是猜测你的应用程序和你的 table,它是 5NF。
大概 id 是一个唯一的列。因此它在功能上确定了每个列集。由于 {id} 的较小子集不是唯一的,因此它是候选键 (CK)。据推测,除了因为那个 CK 而持有的 FD 之外,没有其他 FD 持有。所以 table 在 5NF 中。
但假设还有一个 FD 成立:给定品牌只出现在同一类别中。然后归一化为 5NF 列类别应该被删除,并且应该添加一个新的 table 与品牌 & 类别列和 CK {brand}。
或者假设一个品牌有一个或多个类别,而不是声明类别是其产品类别的行,而是声明类别是其产品品牌的类别。 (很奇怪,从那时起,对于具有多个类别的品牌,table 不会给出产品的类别。)然后归一化也会给出这两个 tables,以及新的 CK {category, brand}。但在这种情况下,这是因为多值依赖性 (MVD),即因为二进制 JD。
PS引入ids与规范化无关
PPS 您似乎认为重复的子行值意味着需要规范化。他们没有。规范化是为了有时用 table 替换 table,而 table 总是加入它。
通过 BCNF 的规范化基于函数依赖性。它不基于列是否包含文本或数字。您似乎认为,因为类别列不止一次包含单词 Beer,所以它需要是 "normalized"。事实并非如此。
那么这里的函数依赖是什么?
- id -> 类别、品牌、类型、价格、数量、描述 [=24=]
- 类别、品牌、类型 -> ID、价格、数量、描述 [=24=]
第二个 FD 可能是错误的。 {brand, type} 可能是决定因素。但我认为很可能某处有一家公司以同一品牌名称生产啤酒和白酒。所以我认为决定因素可能是{category, brand, type}。
那已经在 5NF 中了。 "Splitting" 不会改进这个 table。