我正在将一些数据库重新设计成一个包含数据库,我注意到旧数据库的先前设计者喜欢在他们自己的表中存储类别。例如,假设有一个表格船(bid:整数,bname:字符串,颜色:整数),并且在应用程序中有一个下拉框,允许用户指定船的颜色,然后有一个表格颜色(cid:整数,cname:字符串)。我不会包括颜色表,只是将颜色作为字符串放在船表中。我意识到这减少了颜色名称的冗余存储,但加入船台与颜色表“值得”的运行时成本增加了吗?使用SELECT cname FROM color语句填充下拉列表,而我会在SELECT DISTINCT颜色FROM船上定义一个视图来填充下拉列表。
示例很简单,但在我重新设计的系统中会发生多次,即使对于只有两个选项的类别也是如此。这导致许多表只有2个字段。有些只有1个字段(我还没有想出它们的用途,但我认为它们只是用于填充下拉列表,而实际的表格也包含这些值。)
答案 0 :(得分:2)
如果这是我的数据库,我会亲自将它们保存在自己的表中。
如果你遇到Boats a,b and c can only come in silver and black
的要求,那么你会感谢你做到了。我已经看到这些类型的请求在很多项目中涌现出来。
如果您只关心查询复杂性,可以创建一个加入所需信息的视图,这样您只需要查询一次而不需要JOIN
。
如果您担心JOIN的性能影响,那么我会考虑创建适当的索引或可能是索引视图。
祝你好运!答案 1 :(得分:2)
当您知道列应具有一组有限的值时,应该告诉dbms强制执行该有限集。处理这种要求的三种最常见的方法是
在这三者中,将外键设置为颜色表会使生活更容易。
我意识到这会减少颜色名称的冗余存储,但是 是加入船台与颜色的额外运行时间成本 表“值得”?
这是一个不同的问题。首先,存储外键值是数据完整性的一种形式,而不是冗余的形式。密钥的存在有两个原因:1)识别现实世界中的东西,2)存储在其他表中。 (因为密钥标识的东西与另一个表相关。)
其次,如果您通过为其分配任意ID号来识别颜色,则 使用JOIN来获取人类可读的信息。但是,颜色与许多属性一样,带有他们的身份。如果您使用颜色的名称本身(“红色”,“橙色”等)或使用人类可读的代码作为名称(“R”,“O”等),您不需要连接。你做仍然需要一个颜色表(或CHECK()约束),因为船中的列具有一组有限的值,并且dbms应该强制使用该有限的一组值。 / p>
所以你可以做这样的事情。
create table boats (
boat_id integer primary key,
registered_name varchar(35) not null,
hull_color varchar(10) not null references hull_colors (color)
);
create table hull_colors (
color varchar(10) primary key
);
insert into hull_colors values ('red'),('orange'),('yellow') etc.
这两个表都是5NF。
答案 2 :(得分:1)
通常最好有一个规范化的数据库。
但是,在您的示例中,您可以使用Categories(ID, Type, Name)
表格并将颜色存储为( 3, "Color", "Blue" ), ( 4, "Color", "Red" ), ...
这样,您可以在同一个表格中同时存储更多类别,并将它们分别存储。填充下拉列表需要简单选择表格select ID, Name from Categories where Type = 'Color'
。
编辑:请注意,这个解决方案违反了数据库规范化的第一条规则,正如@Catcall所说。 3NF表格为Colors(ID, Name)
。这样,您可以使用ID
来引用某种颜色。
使用select distinct color from boats
填充下拉列表有许多缺点,例如,如果Boats表不包含任何记录,该怎么办?然后,您的选择将不返回任何内容,并且下拉控件将不会填充任何值。另一个问题是当您的字段包含'Red'
和'red'
或类似字段时。查看有关Database Normalization here
答案 3 :(得分:0)
听起来这些是查找表,因此如果最终用户想要添加其他颜色,那么他们可以将其添加到数据库中,然后它将沿着UI传播。这也进入了正常化阶段。如果只有一个地方引用了颜色,那么查找表就不是必需的。但是,如果有多个表格可以为不同的东西引用颜色,那么查找表将为您节省大量的麻烦。