首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >最大归一化

最大归一化
EN

Database Administration用户
提问于 2014-02-24 22:58:43
回答 1查看 80关注 0票数 0

我一直在研究规范表单规则,以指导我进行数据库设计和数据存储,我遇到的问题是,一旦我为第一个普通表单(1NF)进行了优化,我想我很可能会一直走下去(即使不是强制性的)。

然而,在我的设计中,有一件事表明,我还没有在网上或书中遇到过这样的例子。

一个例子概念。

我们想要存储一些汽车变体的所有数据。

我们必须储存价值制造,系列,型号,开始年份,年底。

未正规化

代码语言:javascript
复制
+------+--------+-------+------------+----------+
| make | series | model | start year | end year |
+------+--------+-------+------------+----------+
| BMW  |   5    |  E12  |    1972    |   1981   |
| BMW  |   5    |  E28  |    1981    |   1988   |
| BMW  |   5    |  E34  |    1988    |   1996   |
| BMW  |   5    |  E39  |    1995    |   2004   |
+------+--------+-------+------------+----------+

规范化

代码语言:javascript
复制
car_make

+----+------+
| id | make | 
+----+------+
| 1  | BMW  | 
+----+------+

car_series

+----+--------+---------+
| id | series | make_id |
+----+--------+---------+
| 1  |   1    |    1    |
| 2  |   3    |    1    |
| 3  |   5    |    1    |
| 4  |   7    |    1    |
+----+--------+---------+

car_model

+----+-------+------------+----------+-------- --+
| id | model | start year | end year | series_id |
+----+-------+------------+----------+-----------+
| 1  |  E12  |    1972    |   1981   |     3     |
| 2  |  E28  |    1981    |   1988   |     3     | 
| 3  |  E34  |    1988    |   1996   |     3     | 
| 4  |  E39  |    1995    |   2004   |     3     |  
+----+-------+------------+----------+-----------+

在最后一个表中出现了一个问题,我是否也应该在make_id表中包含一个列car_model?

这是有益的,因为我不必加入car_series,然后选择make_id,选择make_id,但是我相信这可能不会坚持规范化,因为我会重复数据(即使它仍然是一个id,它仍然重复)。

这个设计能进一步规范化吗?

另外,关于开始的一年,年终的处理,你们专业人士会怎么做呢?我很好奇,如果有任何范围的技巧来执行完整性(尽管E39重叠,让我们说好像没有日期重叠)。

事先谢谢你的任何想法。

EN

回答 1

Database Administration用户

回答已采纳

发布于 2014-02-24 23:18:57

不,不应该在make_id表中包含列car_model,它是由series_id隐式定义的。如果您需要查看make details,您可以创建一个类似于您的未规范化表的视图。

不,这个设计不能进一步标准化。

要强制年份范围不重叠,可以添加一个触发器(因为MySql不支持检查约束),以确保start_year >= max(end_year)end_year >= start_year

触发器看起来会是这样的:

代码语言:javascript
复制
create trigger trg_car_model_date_range_unique before insert on car_model
for each row
begin
    if new.start_year < (select max(end_year) from car_model) then
        signal sqlstate '45000' set message_text = 'Date range is not unique';
    end if;
    if new.end_year < new.start_year then
        signal sqlstate '45000' set message_text = 'Date range is invalid';
    end if;
end
票数 0
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/59569

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档