代码之家  ›  专栏  ›  技术社区  ›  Kirschstein

对一张有很多责任的桌子的最佳方法

  •  0
  • Kirschstein  · 技术社区  · 16 年前

    我目前正在创建各种申请表的电子版本。每个表单都很可能需要一些关于用户的特定数据。为了便于讨论,这里有一个简化的版本。

          Form                                 Required Info
     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯              ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯             
     Mileage Claim               Does user have a lease car?
     Overtime Claim              Contract type (permanent/temp). Salary
     Procurement Request         User role (supervisor, technician)
    

    我目前不知道这个系统总共会有多少个表单,或者他们可能需要什么其他关于用户的额外信息。但可以假设他们都需要标准的信息,比如姓名、电子邮件、工资单号码等。

    你会采取什么方法来模拟这个模型?把它全部扔到用户表中,还是创建大量引用用户的表?

    4 回复  |  直到 16 年前
        1
  •  1
  •   Steve B.    16 年前

    把它全部放到用户表中是一个不断增长的方法” Ball of Mud “模式。最终,您将得到一个包含300个字段的表——名字、姓氏、地址、工作地址、夏季地址、OwnsaleaseCar、LikeSpizza等等。

    我会让他们共享一个用户对象。用户将反映他们所有人的共同点。如果他们使用不同类型的用户(例如,有些人拥有个人信息,有些人拥有完全不同的数据集),那么拥有用户和员工可能是合理的。主要的一点是,我不会试图把不同的类型塞进同一张表中。

    编辑- 另外一点是,将不同的数据类型组合在一起会使实现完整性变得不可能——假设将“rentalcaruser”和“employeeuser”组合到同一个表中,并且为rentalcaruser提供字段“doesusherhaveleasecar”。那么,它将是空的,或者对员工有一个无意义的默认值,如果你真的想强制每一个租车用户必须拥有这些信息,你就不能在数据库级别强制执行它(字段!=空),因为您有其他用户不适用该值。为员工添加一个触发器来填写“NA”并没有帮助,因为这样你就有了一大堆“NA”记录,而且你很难判断这是正确的还是丢失的数据。

        2
  •  0
  •   Gary Willoughby    16 年前

    我将以模块化的方式设计数据库,使用用户名(如果强制使用唯一性)或用户ID作为引用所有相关信息的键。您将做得更好,并从将信息模块化为多个表中了解更多信息。

        3
  •  0
  •   Tom Ritter    16 年前

    你有三张桌子。

    users_tbl
    ---------
    id
    name
    ...
    
    
    form_tbl
    --------
    id
    name
    ...
    
    
    formRequirement_tbl
    -------------------
    form_requirement_id
    form_id
    and/or Flag
    

    现在你有了超复杂的逻辑。

    bool CheckRequirements($formid, $userid)
    {
        $arrayOfFormRequirementIds = goGetFormRequirementIds($formid);
        $result = false;
        foreach($requirementId,$andOrFlag in $arrayOfFormRequirementIds)
        {
           switch($requirementId)
           {
              case 1:
                   $sql = "Select 1 from leases where userid = $userid and active = 1";
                   $result |= executeSQLQueryScalar($sql);
                   if($andOrFlag == AND && !$result) 
                        return false;
                   break;
              ...
            }
         }
      return $result;
    }
    

    现在,整件事都是从一个巨大的开关声明中引出的吗? 是的 . 但是通过这样做,您可以使关于用户可以填写哪些表单的逻辑非常复杂:

    • 用户的电话号码不能为空
    • 用户必须有一个有效的汽车租赁(这可能很难确定)
    • 用户必须在20到50岁之间,拥有活跃的电子邮件,并且居住在蒙大拿州,除非他超过60岁并且居住在佛罗里达州。

    如果只存储列名来检查空值,就无法执行复杂的逻辑。如果在用户表(如“canFilloutMarriageForm”)中存储单个位,则必须等到更新这些位的作业运行后,用户才能填写MarriageForm。

        4
  •  0
  •   Scott Vander Molen    16 年前

    似乎您不熟悉数据库规范化,所以我建议您阅读一些相关的教程。这里只有一个例子: http://dev.mysql.com/tech-resources/articles/intro-to-normalization.html

    您要从要求您在数据库中建模的纸质表单开始。表单上的每个字段都将成为(未规范化)数据库中的字段。因为您处理的是多个表单,所以可能会有一些共同的字段。这是一个很好的提示,您应该将这些抽象到一个单独的表中。例如,听起来这三个表单都有一个地方让员工写下自己的名字来标识谁在填写表单,所以您需要一个员工表。

    从那里开始,只需遵循互联网上众多规范化教程中的一个。第三种正常形态是大多数人所能达到的,但即使第二种正常形态也有所改善。你可能经常会发现你的设计已经是第一个正常的形式了。