数据库设计:使用映射表或直接在表中包含数据

时间:2015-04-12 16:10:12

标签: database database-design relational-database

我正在编写一个项目管理Web应用程序,仅供练习。基本思想是用户可以将项目添加到应用程序,然后通过界面管理与项目相关的任务和约会。我目前正在设计数据库,我想知道最佳实践将在这里指示。

到目前为止我有4张桌子:

+----------+   +-------------+   +--------------+   +-------------+
|Users     |   |Projects     |   |Tasks         |   |Appointments |
+----------+   +-------------+   +--------------+   +-------------+
|id        |   |id           |   |id            |   |id           |
|username  |   |project_name |   |task_name     |   |appt_name    |
|fname     |   |project_desc |   |task_details  |   |appt_details |
|sname     |   |             |   |task_deadline |   |appt_date    |
+----------+   +-------------+   +--------------+   +-------------+

我将基本关系视为:

  • 一个user可以有多个projectstasksappointments
  • 一个project可以有多个userstasksappointments
  • 一个task可以包含多个users,但只能与一个project相关联。 task无法与appointment相关联。
  • tasks的规则也适用于appointments

我的问题是:何时适合使用映射表,何时适合将数据直接包含在关联表中?我对我的例子的看法是:

  • 为每个users-projects / tasks / appts都有一个映射表,因为每种类型可以有很多用户,每个用户可以有很多类型
  • 任务和约会表中的
  • 包含一个project_id字段,可用于将任务和约会与项目相关联,从而将该项目的用户关联起来。

这是正确的方法还是有更好的解决方案?我对数据库设计还是比较陌生的,所以我真的很感激一些建设性的批评

1 个答案:

答案 0 :(得分:2)

一个建议可能听起来不像技术,更像是语法。在描述您的实体及其相互关系时,请提及甚至考虑表,列或其他任何内容。在设计过程的开始,它们是实体 - 不是表,属性 - 而不是列。不要太早影响物理设计。

使用与关系紧密匹配的单词。例如,我怀疑在正常的谈话过程中,一个用户会问另一个用户是否有关系"有一个项目。它会更像是"你是否参与了这个项目?"或者"你在做这个项目吗?"因此,用户可以在许多项目中参与,并且项目中可以包含许多涉及的用户。具体说明关系是什么,但你不必得到肛门。可能有几个紧密配合 - 选择一个并继续。

对于地图表,当你描述多对多关系时,你真的没有多少选择。

您可以选择一对多的关系。例如,任务是为"执行的。只有一个项目。这意味着FK to Project可以成为Task元组的一部分。但您也可以实现一对多映射表。这种情况通常是在这种关系似乎至少有可能在未来的某个时间发展为多对多的情况下完成的。

多对多和一对多映射表之间的差异是微不足道的:

create table UserProjectMap(
    int    UserID  not null,
    int    ProjectID not null,
    constraint FK_UserProject_User foreign key( UserID )
        references Users( ID ),
    constraint FK_UserProject_Project foreign key( ProjectID )
        references Projects( ID ),
    constraint PK_UserProjectMap primary key( UserID, ProjectID )
);

create table TaskProjectMap(
    int     TaskID not null,
    int     ProjectID not null,
    constraint FK_TaskProject_Task foreign key( TaskID )
        references Tasks( ID ),
    constraint FK_TaskProject_Project foreign key( ProjectID )
        references Projects( ID ),
    constraint PK_TaskProjectMap primary key( TaskID )
);

如果你错过了它,它就是每个定义的最后一行。

将一对多映射表转换为多对多很容易 - 只需在一侧删除唯一约束。或者,在上面的示例中,重新定义PK以包括两个FK字段。这意味着没有结构上的变化,当设计已经使用了很长一段时间时,这是非常困难的 - 除非你提前为它们做好了准备。

但那是500级的工作。

哦,还有一条建议。不要过于快速地进行非规范化或进行任何更改,而不是为了使开发人员更容易进行查询或DML。数据库的唯一目的(以及您作为设计者的目标)是满足用户的需求,而不是数据库开发人员的需求。最重要的是数据完整性。不要为了更高的性能或易于维护而牺牲数据完整性。 DBA可能会发牢骚,但用户会很感激 - 并且最终支付你工资的用户也是如此。