我需要存储与“项目”相关的数据,其中将存在各种不同的项目类型,所有项目都具有公共属性,然后每个类型都有其自己的附加属性。我期望这是一个共同的要求;最佳实践解决方案是什么?我们正在使用SQL Server。项目和专用项目:具有重复列,主表和详细表或多个表的多个表?
让我们用一个虚构的例子:
车辆有
- 价格
- 让
- 型号
- 所有者
(在我们的真实数据,会有10-15公共列)
汽车是车辆加:
- 风格(轿车,运动等)
- 颜色
- EngineSize
Boat is a vehicle plus:
- 排量
- PortOfOrigin
...等。对于几种类型的东西。在我们的实际数据中,每种专业类型通常会添加2-5列;将有5种类型开始。我们将随着时间的推移添加类型,但可能只有总共3或4个(如果有的话)。添加类型需要开发,所以它不像“标签”可以被最终用户无条件地添加。我们假设添加一个类型将需要更改数据库和客户端层,也可能需要更改中间层。这很好。
我们会对所有物品(车辆,在上面的例子中)做很多查询;我们很少只担心特定项目类型(汽车,小船)的细节。
我看到四种方式来存储这些数据:
- 车,船等单独的表,有重复列。
- 一张表,其中包含
Vehicle
数据,附加Car
数据的表以及附加Boat
数据的表。 - 一个项目表,一个单独的项目属性表,每个附加属性具有一行。例如,细节的软模式。
- 一个表的泛型列给出的含义只有非DB代码。
查看每个:
单独的表用于汽车,船等,具有重复列。例如,大致为:
CREATE TABLE [Cars] ( [Id] IDENTITY PRIMARY KEY, [Price] DECIMAL (19, 4), [Make] NVARCHAR(200), [Model] NVARCHAR(200), [Owner] INT, [Id] INT PRIMARY KEY, [Style] NVARCHAR(200), [Color] NVARCHAR(200), [EngineSize] DECIMAL(19, 2) ) CREATE TABLE [Boats] ( [Id] IDENTITY PRIMARY KEY, [Price] DECIMAL (19, 4), [Make] NVARCHAR(200), [Model] NVARCHAR(200), [Owner] INT, [Id] INT PRIMARY KEY, [Displacement] DECIMAL(19, 4), [PortOfOrigin] NVARCHAR(200) )
很简单,汽车走在
Cars
和船只Boats
去。如果我们添加更多的车辆类型,我们添加一个表格。如果我们添加另一个通用列,我们必须返回并将其添加到所有车辆表。通常可以通过所有表格的联合视图来完成对车辆的报告(注意Id
栏)。一张表,其中有
Vehicle
数据,一张额外的Car
数据,以及一张额外的Boat
数据表。例如,大致为:CREATE TABLE [Vehicles] ( [Id] IDENTITY PRIMARY KEY, [Price] DECIMAL (19, 4), [Make] NVARCHAR(200), [Model] NVARCHAR(200), [Owner] INT, [Type] INT -- A type ID, e.g. "Car" vs. "Boat" ) CREATE TABLE [Cars] ( [Id] INT PRIMARY KEY, [Style] NVARCHAR(200), [Color] NVARCHAR(200), [EngineSize] DECIMAL(19, 2) ) CREATE TABLE [Boats] ( [Id] INT PRIMARY KEY, [Displacement] DECIMAL(19, 4), [PortOfOrigin] NVARCHAR(200) )
所以每一辆车将在
Cars
在Vehicles
和一个联排一排。每艘船将在Boats
在Vehicles
和一个联排一排。如果我们添加更多的车辆类型,我们添加一个表格。报告针对一般车辆可以针对刚刚Vehicle
表来完成。当检索特定的Car
或Boat
的详细信息时,我们使用连接。一个项目表,一个单独的项目属性表和一个附加属性的行。例如,细节的软模式。例如,大致为:
CREATE TABLE [Vehicles] ( [Id] IDENTITY PRIMARY KEY, [Price] DECIMAL (19, 4), [Make] NVARCHAR(200), [Model] NVARCHAR(200), [Owner] INT, [Type] INT ) CREATE TABLE [VehicleDetails] ( [VehicleId] INT, [Name] NVARCHAR(200), [Value] NVARCHAR(MAX) )
所以每次租车获取
VehicleDetails
在Vehicles
和三排一排(每一个“样式”,“颜色”和“EngineSize”)。报告主要是针对Vehicle
表完成的。关于细节的报道开始变得杂乱无章。软模式有其自己的位置,主要是围绕用户定义的数据,但我认为这不是一个好的选择。只有非DB代码中给出的含义通用列一个表:
CREATE TABLE [Vehicles] ( [Id] IDENTITY PRIMARY KEY, [Price] DECIMAL (19, 4), [Make] NVARCHAR(200), [Model] NVARCHAR(200), [Owner] INT, [Type] INT, [Detail01] NVARCHAR(MAX), [Detail02] NVARCHAR(MAX), [Detail03] NVARCHAR(MAX), [Detail04] NVARCHAR(MAX), [Detail05] NVARCHAR(MAX), [Detail06] NVARCHAR(MAX), [Detail07] NVARCHAR(MAX), [Detail08] NVARCHAR(MAX), [Detail09] NVARCHAR(MAX), [Detail10] NVARCHAR(MAX) )
因此汽车数据将指定样式为
Detail01
,颜色以Detail02
,并EngineSize到Detail03
;为船,我们就会把排量在Detail01
和PortOfOrigin在Detail02
。同样,对于最终用户定义的模式也可能有这样的地方,但我猜测这可能不是一个好的答案,因为您可以控制数据库结构。
是关系数据库严格要求?看起来像使用这个模型的文档数据库会更合适。 – Oded 2012-03-06 13:18:22
@Oded:好问题。在这种情况下,是的,至少在现在,它必须存储在RDBMS中。如果我们得到足够的这些要求,也许我们会用文档数据库来扩充RDBMS。 – 2012-03-06 13:21:25
“我们将随着时间的推移添加更多类型” - 向我表明选项2。软模式(EAV模型)与通用列一样,不是起动器。 – Oded 2012-03-06 13:25:24