我一直在研究规范表单规则,以指导我进行数据库设计和数据存储,我遇到的问题是,一旦我为第一个普通表单(1NF)进行了优化,我想我很可能会一直走下去(即使不是强制性的)。
然而,在我的设计中,有一件事表明,我还没有在网上或书中遇到过这样的例子。
一个例子概念。
我们想要存储一些汽车变体的所有数据。
我们必须储存价值制造,系列,型号,开始年份,年底。
+------+--------+-------+------------+----------+
| 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 |
+------+--------+-------+------------+----------+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重叠,让我们说好像没有日期重叠)。
事先谢谢你的任何想法。
发布于 2014-02-24 23:18:57
不,不应该在make_id表中包含列car_model,它是由series_id隐式定义的。如果您需要查看make details,您可以创建一个类似于您的未规范化表的视图。
不,这个设计不能进一步标准化。
要强制年份范围不重叠,可以添加一个触发器(因为MySql不支持检查约束),以确保start_year >= max(end_year)和end_year >= start_year。
触发器看起来会是这样的:
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;
endhttps://dba.stackexchange.com/questions/59569
复制相似问题