我想在数据库设计中删除表字段中的冗余

时间:2015-09-24 10:12:05

标签: sql sql-server database entity-framework database-design

我有两张桌子:

学生大师

  

标识,名字,姓氏,电子邮件,电话   没有,Countryid,STATEID,cityid,Profilepicurl,性别,出生日期。

CoachMaster

  

标识,名字,姓氏,电子邮件,电话   没有,Countryid,STATEID,cityid,Profilepicurl,性别,出生日期,语言

现在你可能会注意到这两个表只有一个共同的字段,只有一个额外的字段,即语言中的语言

我正在考虑制作一个包含表中所有字段的表格,即 UserMaster (包含StudentMaster和CoachMaster),如下所示:

UserMaster

  

Id,休息所有常见字段,语言(来自Coach Master)

我与我的一位经验丰富的开发人员讨论了这个问题,他告诉我只创建一个单独的表格,他向我展示了2个创建 2分隔的2个场景表

  1. 如果我只有一张普通表,那就是UserMaster,如果将来我想在coach master中添加2个额外的字段,那么这个结构就不好了。

  2. 如果我在UserMaster中添加教练所需的那2个额外字段,如果我只想要任何特定的学生详细信息,那么这些额外的2个字段(在我的教练的第1点中添加)也将不必要地获取。

  3. 注意:其他方案也可能只有1个表维护教练和学生的详细信息。

    除此之外,我的朋友告诉我,我不遵循规范化规则,如果我只有一个表只有用户管理员,那么才能确定哪个用户是学生哪个用户是导师我总是必须使用支票 Userinrole 表格,我会像这样保持:

      

    角色大师:身份证,姓名(价值:学生,教练)

         

    UserInRole:RoleId(对RoleMaster Id的引用),UserId(存储或者   学生或教练)

    当我有任何 id 时,我总是必须找到是否是教练r学生。

    那么有人可以帮助指导我如何创建一个好的结构来解决这两个场景并避免在这个表中不必要地创建重复的字段吗?

2 个答案:

答案 0 :(得分:2)

SQL并没有为"一个"提供非常好的支持。关系。有方法,但它们往往有点笨拙。

因为您正在考虑"用户"除了学生"和"教练",听起来你有另一个实体。 "用户"是"学生"或"教练"。

我想我会用两种方式解决你的问题。

两者都以Users表开头,包含学生中的所有字段。此 是用户,学生和教练的主键。所有用户都被视为学生,除非他们有证明自己是教练。这个证据是什么?

一种可能性是type表中的Users列以及所需的其他字段。这通常是解决这个问题的一种非常合理的方法。

第二个是添加表Coaches,其主键为CoachId,也是UserId的外键。这包含有关教练的其他信息。此外,它还可以在需要的地方轻松设置外键关系。

答案 1 :(得分:1)

你当然可以为学生和教练维护一张桌子,但是,正如你已经注意到的那样,这有可维护性问题。但是,您(或您朋友的)分析存在一个缺陷。如果您有一个表格,其中一个指示器显示用户类型(例如,'S'或'C'),其中包含如下查找表:

ID   Name     <other>
==   ====     =======
 S   Student  ...
 C   Coach    ...

从Users表中的指示符字段到此表的FK引用将强制执行用户必须是一个或另一个而不是其他任何内容的规则。但是,查询并不总是必须加入此表。执行“插入Users”表或更改此指标字段值的更新时,系统将验证该表中是否存在FK的值。否则,只有当想要获取存储在那里的其他数据时,查询才会加入此表。

话虽如此,除非你知道你的设计在很长一段时间内会非常稳定,否则我会建议一个超级的子设计。可以在此处找到类似问题的更详细答案:

Designing relationships around an inheritance structure

在您的情况下,通用或超级Masters表看起来像您当前的StudentMaster表,并添加了MasterType字段:

create table Masters(
    ID         int not null auto_generated primary key,
    ...
    MasterType char( 1 ) not null,
    ...
    constraint FK_Masters_Type foreign key( MasterType )
        references MasterTypes( ID ),
    constraint UQ_Masters_Type unique( ID, MasterType )
);

FK强制将该条目定义为学生或教练。然后StudentMaster表很简单,因为它没有为通用主数据添加新属性:

create table StudentMasters(
    MasterID    int not null primary key,
    MasterType  char( 1 ) check( MasterType = 'S' ),
    constraint  FK_StudentMasters_Master foreign key( MasterID, MasterType )
        references Masters( ID, MasterType )
);

检查表示只有学生可以插入此表。 FK表示ID必须与Masters表中的条目匹配,并且还必须定义为Student。学生中已定义为Coach(或任何可能的未来类型)的ID值无法存储在StudentMasters表中。

CoachMasters表是相同的,除非它定义语言字段,检查将是“MasterType ='C'”。

现在,您可以在从其他表引用主控时使用选项。对于那些引用Master的FK,无论其类型如何,都可以将引用定义到Masters表。如果它只能是Coach(CoachedBy),则可以对CoachMasters表进行引用。因此,学生的ID值永远不会意外地插入该字段中。与仅涉及学生的参考文献相同。

另一个建议:在这些表格前面加上两个视图,CoachMasters和StudentMasters(将表重命名为其他内容)。然后你的应用程序可以获得教练或学生的信息,甚至不知道底层结构。视图上的触发器将允许所有操作通过视图。这使您可以在需要时更改表的物理布局。只需重新定义视图和触发器,应用程序代码根本不需要更改。这一个技巧可以大大提高数据库的可维护性。

相关问题