数据库设计:使用映射表或直接在表中包含数据
Database Design: Use mapping tables or include data directly in tables
我正在编写一个项目管理 Web 应用程序,只是为了练习。基本思想是用户可以将项目添加到应用程序,然后通过界面管理与项目相关的任务和约会。我目前正在设计数据库,我想知道这里有什么最佳实践。
到目前为止我有 4 个 table:
+----------+ +-------------+ +--------------+ +-------------+
|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
可以有多个projects
、tasks
和appointments
.
- 一个
project
可以有多个users
、tasks
和appointments
。
- 一个
task
可以有多个users
,但只能关联一个project
。 task
不能与 appointment
. 相关联
tasks
的规则也适用于 appointments
。
我的问题是:什么时候 suitable 使用映射 tables 什么时候 suitable 直接在关联的 table 中包含数据?我对我的例子的看法是:
- 每个users-projects/tasks/appts都有一个映射table,因为每种类型可以有很多用户,每个用户可以有很多每种类型
- 在任务和约会 table 中包含一个
project_id
字段,可用于将任务和约会与项目以及该项目的用户相关联。
这是正确的方法还是有更好的解决方案?我对数据库设计还很陌生,所以我非常感谢一些建设性的批评
一个建议可能听起来不像是技术建议,更像是语法建议。在描述您的实体及其彼此之间的关系时,不要提及甚至考虑table、专栏或其他内容。在设计过程的开始,它们是实体——不是 tables,属性——不是列。不要过早地影响物理设计。
做 使用与关系密切匹配的词。例如,我怀疑在正常的对话过程中,一个用户会问另一个用户是否 "have a relationship" 有一个项目。它会更像 "Are you involved in this project?" 或 "Are you working on this project?" 所以一个用户可以 参与 许多项目,一个项目可以有很多用户 参与 在里面。具体说出这种关系是什么,但你不必为此大惊小怪。可能有多个匹配项 -- 选择一个并继续。
至于映射table,当你描述多对多关系时,你真的没有太多选择。
您确实可以选择一对多关系。例如,一项任务是 "performed for" 只有一个项目。这意味着到项目的 FK 可以是任务元组的一部分。但是你也可以实现一对多的映射table。当这种关系似乎至少有可能在未来的某个时候演变成多对多时,通常会这样做。
多对多和一对多映射之间的区别table是微不足道的:
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 )
);
如果你错过了,这是每个定义的最后一行。
将一对多映射 table 转换为多对多很容易——只需在一侧删除唯一约束即可。或者,在上面的示例中,重新定义 PK 以包含两个 FK 字段。这意味着没有结构变化,当设计已经使用了很长时间时,结构变化是极其困难的——除非你提前做好了准备。
不过那是500级的作品。
哦,再提一个建议。不要太快去规范化或进行任何更改,除非这样做会使开发人员的查询或 DML 更容易。数据库的唯一目的(以及您作为设计者的目标)是满足用户的需求,而不是数据库开发人员。在需求列表的顶部是数据完整性。不要为了提高性能或便于维护而牺牲数据完整性。 DBA 可能会抱怨,但用户会感激 - 最终支付您薪水的是用户。
I'm currently designing the Database and I was wondering what best practice would dictate here
最佳实践规定必须将数据建模为数据,而不考虑用途或应用程序。不考虑平台也是如此,但是现在世界颠倒了wards,首先选择平台。
建模意味着您首先确定并考虑实体,然后再考虑要用它们做什么(例如 "mapping")。
没有选项
My question is: when is it suitable to use mapping tables
这是正常的方法。
- 正确
- 理论上成立
- 允许用户期望数据库具有的所有功能和能力
- 例如。聚合、单个或多个项目(列表的子集)搜索非常快等
- 易于扩展
- 防止table错误
- 给你筹码,你可以在天堂兑现。
and when is it suitable to include the data directly in the associated table?
从来没有。这将在单列中创建一个逗号分隔的列表。
- 不正确
- 无理论依据
- 打破第一范式
- 无能者的宠儿(他们不仅不知道规则,而且不知道什么时候他们会违反他们 知道的几条规则)
- 无法使用数据库特性和功能
- 例如。搜索并确定特定用户是否正在处理项目将导致 tablescan
- 结果不是数据库,它是一个记录归档系统
- 难以扩展
- 你会花一半的时间去修复预防table的错误,另一半的时间在想着如何在不让任何人注意到的情况下替换它
- 保证你在地狱中有一个特定的地方,第六层,有欺诈和骗取工人工资的人,比谋杀低一级,比恋童癖和war贩子
高一级
have a mapping table for each of users-projects/tasks/appts because there can be many users for each type and many of each type per user
一般来说,是的。但这还不清楚。 "Type"敲响了警钟,听起来你打算拥有一个支持所有可能性的table;可为空的外键;等等。参考上面的"Never"。
应该有一个关联Table(不是"mapping")只在那些需要它的table之间,而不是在它们之间每一种可能性。每个这样的 table 只与 ("links"、"maps"、"connects") 一对离散的关系相关。
这将在规范化完成后解决,接下来...
考虑
这个要求听起来有点可疑。我不接受那些 table 都是孤立的、零碎的事实。考虑:
首先,Tasks 可能是 Project 的子项(您已经暗示,这种依赖关系应该是明确的)。同样,Appointments 应该是 Project 的子项。如同,任务不能存在,除非在项目的上下文中。约会也是如此。
然后你必须评估用户是否应该与项目相关(如需求中给出的那样)。在我看来,一个用户被分配给一个任务(因此与项目相关,因为任务属于一个项目),而不是分配给项目中的所有任务。同样对于 User::Appointment.
如果用户与项目相关(而不是特定任务),根据要求,它看起来太笼统了。特别是如果一个约会应用一个项目,并因此应用到分配给该项目的所有用户。
所以在我看来,目前收到的信息,加上我的建议(尚未得到证实,所以这是薄冰),任命是在较低级别进行的,任务级别,并且可能适用于分配给该任务的所有用户。
在项目级别可能有第二种约会,它适用于分配给项目中所有任务的所有用户的不同集合.
只要我上面的建议是正确的,特别是用户分配给任务,如果在任务级别进行约会,它适用于分配给该任务的所有用户,那么有根本没有关联 ("mapping") Table。
ID 无法提供行唯一性。您如何根据关系数据库的要求确保行的唯一性?
如您所见,在模型初稿中感知到的每个 table 上标记一个 ID 列会削弱、阻止数据建模练习。你需要 10 到 12 个草稿。在第五个左右的某个地方,您将分配键。在 9 或 10,您将分配 ID 给少数需要它们的 table(如果有的话)。
分配 ID 首先保证在 RFS 中实现初稿,这意味着没有数据库完整性,没有数据库功能。
考虑、confirm/dent、讨论等
这是用作讨论平台的图表。请使用它底部的 link,并熟悉 Notation,达到您认为合适的水平。
我正在编写一个项目管理 Web 应用程序,只是为了练习。基本思想是用户可以将项目添加到应用程序,然后通过界面管理与项目相关的任务和约会。我目前正在设计数据库,我想知道这里有什么最佳实践。
到目前为止我有 4 个 table:
+----------+ +-------------+ +--------------+ +-------------+
|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
可以有多个projects
、tasks
和appointments
. - 一个
project
可以有多个users
、tasks
和appointments
。 - 一个
task
可以有多个users
,但只能关联一个project
。task
不能与appointment
. 相关联
tasks
的规则也适用于appointments
。
我的问题是:什么时候 suitable 使用映射 tables 什么时候 suitable 直接在关联的 table 中包含数据?我对我的例子的看法是:
- 每个users-projects/tasks/appts都有一个映射table,因为每种类型可以有很多用户,每个用户可以有很多每种类型
- 在任务和约会 table 中包含一个
project_id
字段,可用于将任务和约会与项目以及该项目的用户相关联。
这是正确的方法还是有更好的解决方案?我对数据库设计还很陌生,所以我非常感谢一些建设性的批评
一个建议可能听起来不像是技术建议,更像是语法建议。在描述您的实体及其彼此之间的关系时,不要提及甚至考虑table、专栏或其他内容。在设计过程的开始,它们是实体——不是 tables,属性——不是列。不要过早地影响物理设计。
做 使用与关系密切匹配的词。例如,我怀疑在正常的对话过程中,一个用户会问另一个用户是否 "have a relationship" 有一个项目。它会更像 "Are you involved in this project?" 或 "Are you working on this project?" 所以一个用户可以 参与 许多项目,一个项目可以有很多用户 参与 在里面。具体说出这种关系是什么,但你不必为此大惊小怪。可能有多个匹配项 -- 选择一个并继续。
至于映射table,当你描述多对多关系时,你真的没有太多选择。
您确实可以选择一对多关系。例如,一项任务是 "performed for" 只有一个项目。这意味着到项目的 FK 可以是任务元组的一部分。但是你也可以实现一对多的映射table。当这种关系似乎至少有可能在未来的某个时候演变成多对多时,通常会这样做。
多对多和一对多映射之间的区别table是微不足道的:
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 )
);
如果你错过了,这是每个定义的最后一行。
将一对多映射 table 转换为多对多很容易——只需在一侧删除唯一约束即可。或者,在上面的示例中,重新定义 PK 以包含两个 FK 字段。这意味着没有结构变化,当设计已经使用了很长时间时,结构变化是极其困难的——除非你提前做好了准备。
不过那是500级的作品。
哦,再提一个建议。不要太快去规范化或进行任何更改,除非这样做会使开发人员的查询或 DML 更容易。数据库的唯一目的(以及您作为设计者的目标)是满足用户的需求,而不是数据库开发人员。在需求列表的顶部是数据完整性。不要为了提高性能或便于维护而牺牲数据完整性。 DBA 可能会抱怨,但用户会感激 - 最终支付您薪水的是用户。
I'm currently designing the Database and I was wondering what best practice would dictate here
最佳实践规定必须将数据建模为数据,而不考虑用途或应用程序。不考虑平台也是如此,但是现在世界颠倒了wards,首先选择平台。
建模意味着您首先确定并考虑实体,然后再考虑要用它们做什么(例如 "mapping")。
没有选项
My question is: when is it suitable to use mapping tables
这是正常的方法。
- 正确
- 理论上成立
- 允许用户期望数据库具有的所有功能和能力
- 例如。聚合、单个或多个项目(列表的子集)搜索非常快等
- 易于扩展
- 防止table错误
- 给你筹码,你可以在天堂兑现。
and when is it suitable to include the data directly in the associated table?
从来没有。这将在单列中创建一个逗号分隔的列表。
- 不正确
- 无理论依据
- 打破第一范式
- 无能者的宠儿(他们不仅不知道规则,而且不知道什么时候他们会违反他们 知道的几条规则)
- 无法使用数据库特性和功能
- 例如。搜索并确定特定用户是否正在处理项目将导致 tablescan
- 结果不是数据库,它是一个记录归档系统
- 难以扩展
- 你会花一半的时间去修复预防table的错误,另一半的时间在想着如何在不让任何人注意到的情况下替换它
- 保证你在地狱中有一个特定的地方,第六层,有欺诈和骗取工人工资的人,比谋杀低一级,比恋童癖和war贩子 高一级
have a mapping table for each of users-projects/tasks/appts because there can be many users for each type and many of each type per user
一般来说,是的。但这还不清楚。 "Type"敲响了警钟,听起来你打算拥有一个支持所有可能性的table;可为空的外键;等等。参考上面的"Never"。
应该有一个关联Table(不是"mapping")只在那些需要它的table之间,而不是在它们之间每一种可能性。每个这样的 table 只与 ("links"、"maps"、"connects") 一对离散的关系相关。
这将在规范化完成后解决,接下来...
考虑
这个要求听起来有点可疑。我不接受那些 table 都是孤立的、零碎的事实。考虑:
首先,Tasks 可能是 Project 的子项(您已经暗示,这种依赖关系应该是明确的)。同样,Appointments 应该是 Project 的子项。如同,任务不能存在,除非在项目的上下文中。约会也是如此。
然后你必须评估用户是否应该与项目相关(如需求中给出的那样)。在我看来,一个用户被分配给一个任务(因此与项目相关,因为任务属于一个项目),而不是分配给项目中的所有任务。同样对于 User::Appointment.
如果用户与项目相关(而不是特定任务),根据要求,它看起来太笼统了。特别是如果一个约会应用一个项目,并因此应用到分配给该项目的所有用户。
所以在我看来,目前收到的信息,加上我的建议(尚未得到证实,所以这是薄冰),任命是在较低级别进行的,任务级别,并且可能适用于分配给该任务的所有用户。
在项目级别可能有第二种约会,它适用于分配给项目中所有任务的所有用户的不同集合.
只要我上面的建议是正确的,特别是用户分配给任务,如果在任务级别进行约会,它适用于分配给该任务的所有用户,那么有根本没有关联 ("mapping") Table。
ID 无法提供行唯一性。您如何根据关系数据库的要求确保行的唯一性?
如您所见,在模型初稿中感知到的每个 table 上标记一个 ID 列会削弱、阻止数据建模练习。你需要 10 到 12 个草稿。在第五个左右的某个地方,您将分配键。在 9 或 10,您将分配 ID 给少数需要它们的 table(如果有的话)。
分配 ID 首先保证在 RFS 中实现初稿,这意味着没有数据库完整性,没有数据库功能。
考虑、confirm/dent、讨论等
这是用作讨论平台的图表。请使用它底部的 link,并熟悉 Notation,达到您认为合适的水平。