我们的应用程序已经过定制,可以处理许多不同类型的客户,某些设置仅适用于少数或一个客户。而不是不断地将可空列添加到customers表, 我决定添加一个[设置]表,以允许每个设置为一行。
[dbo].[Settings]
[SettingID] [int]
[SettingCode] [nchar](4)
[SettingDescription] [nvarchar](255)
然后通过多对多表
将其链接到[Customers]表[dbo].[Customer_Settings]
[Customer_SettingsID] [int]
[CustomerID] [int]
[SettingID] [int]
我的问题是如何处理这些设置中的许多设置需要[Customer_Settings]表上的其他数据类型。
例如,我们可以将一个设置设置为需要时间数据类型的“最新交付时间”,或者另一个设置为“需要一个int的分钟到期”。
我能想到的两种方法是将可为空的列添加到[Customer_Settings]表中,如:
[dbo].[Customer_Settings]
[Customer_SettingsID] [int]
[CustomerID] [int]
[SettingID] [int]
[ValueTime] [time] NULL
[ValueInt] [int] NULL
...
这看起来很糟糕。
我能想到的另一种方法是将子表添加到[Customer_Settings]表中,如:
[dbo].[Customer_Settings_Int]
[Customer_Settings_Int_ID] [int]
[Customer_SettingsID] [int]
[Value] [int]
这似乎是规范化的,但也很麻烦。如果其中一个显然更好或者有其他选择,请告诉我。谢谢!
答案 0 :(得分:0)
您选择的解决方案称为Entity-Attribute-Value (EAV.)最常见的方法是将所有值存储为字符串。有些人添加了一个包含正则表达式或类似表达式的验证器列,该列由客户端或更新值的t-sql函数验证。
使用可以为空的列要清晰得多。
答案 1 :(得分:0)
看起来您可能能够将多组属性收集到逻辑分组中,而不是单例属性列表。你提示"交付的东西"和"到期的东西"这可能是两个这样的分组。在查找表中创建这些分组的列表,如下所示:
ID Name Description
D Deliverable Something that is delivered
E Expirable Something that expires
然后为客户和分组创建一种交集表(具有分组类型)
create table CustGrouping(
CustID int not null references Customer( ID ),
GroupID int auto_generated,
GroupType char( 1 ) not null references Groupings( ID ), -- the table above
constraint PK_CustGrouping primary key( CustID, GroupID ),
constraint UQ_Group_Type unique( GroupID, GroupType )
);
PK会防止意外地将客户与同一个分组多次配对。当GroupID本身是唯一的时,为什么要在(GroupID,GroupType)上创建唯一约束?所以它可以作为外键的参考点。
每个分组都需要一个单独的表格。这只是一个:
create table Deliverables(
ID int not null primary key,
TypeID char( 1 ) not null check( TypeID = 'D' ),
DeliveryDate date not null,
..., -- all other fields that are associated with deliverables
constraint FK_Deliverables_CustGrouping foreign key( ID, TypeID )
references CustGrouping( GroupID, GroupType )
);
检查约束显示了如何只将可交付数据写入该表。
以下是操作顺序:
其他分组也采用相同的操作。分组ID确保该组的FK只能引用正确类型的分组。它还可以让您知道哪个表包含数据,并且这些数据对于每种分组都可以完全不同。它的可扩展性是,为了添加新类型的分组,将定义插入到Groupings表中,创建一个表来包含所需长度和格式的数据,并从那里开始。
我还建议创建视图以显示每种分组的客户数据。例如,视图CustomerDeliverables
显示带有可交付物的客户数据。因此,当应用程序的一部分只使用可交付成果时,它不需要知道如何将其存储在数据库中的细节。视图上的触发器可以轻松创建,删除和操作分组数据。