我正在开发一个分类广告网站。而且我完全停留在数据库设计级别。广告只能属于 1 个类别。在我的数据库中,我有一个名为"ads"的表,该表具有所有广告通用的列。
CREATE TABLE Ads (
AdID int not null,
AdDate datetime not null,
AdCategory int not null,
AdHeading varchar(255) not null,
AdText varchar(255) not null,
etc...
);
我也有很多类别。例如,在"汽车"类别中发布的广告具有其他列,例如品牌、型号、颜色等。在"住房"中发布的广告具有房屋类型、平方英尺等列。等。。。我做了这样的事情:
CREATE TABLE Cars (
AdID int not null,
CarMake varchar (255) not null,
CarModel varchar(255) not null,
...
);
CREATE TABLE Housing (
AdID int not null,
HousingType varchar (255) not null
...
);
其中的AdId是Ads的外键。
但是当我需要从广告中检索信息时,我必须查找所有这些附加表,并检查广告中的AdId是否等于这些表中的AdId。对于每个类别,我都需要一个新表。我最终会得到大约 15 张桌子。我有一个想法,在 Ads 表中有一个布尔列,如 is_Cars、is_Housing 等,但有 15 列,其中 14 是 NULL 似乎很糟糕。有没有更好的方法来设计这个数据库?我需要我的数据库处于第三范式,这是最重要的要求。
不要太担心 - 这是一个众所周知的困境,没有"银弹",所有解决方案都有一些权衡。您的解决方案对我来说听起来不错,并且在行业中常用。不利的一面是,正如你提到的,它有JOINS(无论如何,这是一个众所周知的规范化的权衡),而且每个新产品类型都需要一个新的TABLE。从好的方面来说,表结构精确地反映了您的业务逻辑,它在存储中是可读的和高效的。
据我了解,您的另一个建议是一个表格,其中每行都有一个"类型"指示 - 汽车、房子等(顺便说一句,不需要多列,例如"is_car"、"is_house"——拥有单列"类型"更简单,例如 type=1 表示汽车,type=2 表示房屋等)。然后是多个列,其中一些列未用于某些产品类型。优点是能够在不更改数据库架构的情况下动态添加新类型(甚至是用户定义的类型)。也没有"加入"。不利的一面是,您将存储和检索大量"空"单元格,并且架构的描述性也会降低:例如,很难放置约束"carModel 列不可为空",因为它对于房屋是可为空的(您可以使用触发器,但它的可读性较低)。
就个人而言,我更喜欢第一个解决方案(当然取决于用例,但第一个解决方案是我的第一直觉)。在考虑权衡之后,我可以放心地使用它,例如,理解我容忍这些 JOIN 作为可读和紧凑模式的支付。
第一,您混淆了类别和产品规格。
第二,您需要阅读表继承。
如果您不介意空值,请使用单表继承。所有"类别"(汽车,房屋等)都放在一个表中,并有一个"类型"列。
如果您不喜欢空值,请使用类表继承。使用将类别外键指向的主键创建一个主表。为每种类型(汽车、房屋等)创建子表,其主键也是主表的外键。使用像Hibernate这样的ORM更容易。