【问题标题】:I want to remove redundancy in table fields in my database design我想在我的数据库设计中删除表字段中的冗余
【发布时间】:2015-12-21 21:38:20
【问题描述】:

我有 2 张桌子:

学生硕士

ID、名字、姓氏、电子邮件、电话 否,Countryid,stateid,cityid,Profilepicurl,gender,Dateofbirth.

教练大师

ID、名字、姓氏、电子邮件、电话 否,Countryid,stateid,cityid,Profilepicurl,gender,Dateofbirth,Language。

现在您可能会注意到,这 2 个表只有一个公共字段,除了 1 个额外字段,即 coachmaster 中的 Language

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

用户管理员

Id,其余所有常用字段,Language(来自 Coach Master)

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

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

注意:其他场景也可能存在,只有一张表同时维护教练和学生的详细信息。

除此之外,我的朋友告诉我,我在这里没有遵循规范化规则,如果我只有 一个只有 usermaster 的表,那么只有识别哪个用户是学生和 哪个用户是导师,我总是必须使用加入检查是 Userinrole表,我将像这样维护:

角色大师:Id,Name(Value:Student,Coach)

UserInRole:RoleId(Reference to RoleMaster Id),UserId(存储任意一个 Studentid 或 CoachId)

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

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

【问题讨论】:

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


    【解决方案1】:

    SQL 没有为“one-of”关系提供很好的支持。有一些方法,但它们往往有点笨拙。

    因为除了“学生”和“教练”之外,您还考虑“用户”,听起来您还有另一个实体。 “用户”要么是“学生”,要么是“教练”。

    我想我会以两种方式之一来解决您的问题。

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

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

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

    【讨论】:

    • 你能提供任何简单的结构来描述你的答案吗?
    • @Learning 什么是“简单结构”? (一张图?SQL?)为什么答案明文不够用?
    【解决方案2】:

    您当然可以为 Student 和 Coach 维护一个表,但是,正如您自己注意到的那样,这存在可维护性问题。但是,您(或您朋友)的分析存在一个缺陷。如果您有一个带有显示用户类型(例如,“S”或“C”)指示器的表,其中的查找表如下所示:

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

    从用户表中的指示符字段到该表的 FK 引用将强制执行用户必须是一个或另一个而不是其他的规则。但是,查询不必总是连接到该表。当您执行用户表的插入或更改此指示符字段值的更新时,系统将验证 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。 Student 中已定义为 Coach(或任何可能的未来类型)的 ID 值不能存储在 StudentMasters 表中。

    CoachMasters 表是相同的,只是它定义了 Language 字段并且检查将是“MasterType = 'C'”。

    现在您可以在从其他表中引用母版时进行选择。对于那些引用 Master 的 FK,无论类型如何,都可以将引用定义到 Masters 表。如果它只能是一个教练 (CoachedBy),则可以参考 CoachMasters 表。因此,学生的 ID 值永远不会被意外插入到该字段中。必须仅引用学生的引用也是如此。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多