数据库模式 - 混合多对多和一对多关系

时间:2013-06-04 19:35:58

标签: sql many-to-many one-to-many

我有一个用户模型和一个任务模型。

用户创建任务。这看起来很简单: 该任务有一个user_id foreign_key

但现在我们介绍分享。现在,任务与用户有多对多的关系,但属于所有者。

我可以: - 将user_id保留在任务上(可能将其重命名为'owner_id') - 并且具有多对多连接表(user_tasks或shared_user_tasks)仅模拟已共享的任务。

或者我可以: - 删除任务上的user_id - 并使user_tasks与布尔'is_owner'建立一个纯粹的多对多关系,告诉我该用户是否是所有者

或者我可以: - 删除任务上的user_id - 并使user_tasks列出shared_user_id和owner_id 这意味着对于某些记录,shared_user_id和owner_id将是相同的数字(比上面的查询更难)

根据最佳做法哪个更健全?

感谢您的时间。

而且,正如第一个答案所暗示的那样(尽管我有点因为某些原因而不愿意接受),从概念上讲,这两个角色是不同的。一个是任务所有者,另一个是与他们共享任务的人。

2 个答案:

答案 0 :(得分:1)

“真正的”正确答案将取决于这些表的使用方式,但听起来选项#1应该是您的解决方案(task_table.owner_id和单独的M:M user_tasks表)。即使任务所有者和任务用户共享相同的源表,它们在概念上也是不同的,应该这样对待。表连接的逻辑也会更加清晰。

答案 1 :(得分:1)

正常化到救援!可能.....(虽然根据您的使用情况,可能存在对性能进行非规范化的余地)

Users - 存储有关用户(谁)的信息

Tasks - 存储有关任务的信息(任务是什么,它做什么等)

UserTasks - M-> M映射。

UserTaskTypes - 商店(“所有者”,“共享”,“顾问”,“经理”等)

UserTasks上的

可能看起来像这样(tsql)

CREATE TABLE UserTasks (
    [TaskID] INT,
    [UserID] INT,
    [UserTaskTypeID] INT,

    FOREIGN KEY FK_UserTasks_TaskID ([TaskID])
            REFERENCES Tasks ([TaskID]),

    FOREIGN KEY FK_UserTasks_UserID ([TaskID])
            REFERENCES Users ([UserID]),

    FOREIGN KEY FK_UserTasks_UserTaskTypeID ([UserTaskTpyeID])
            REFERENCES UserTaskTypes ([UserTaskTypeID]),

    PRIMARY KEY PK_UserTasks ([TaskID], [UserID], [UserTaskTypeID])
 )

根据您的业务规则,您可以添加CHECK CONSTRAINTS以强制执行每项任务只有一个所有者等。

为此选择聚簇索引可能就像聚类PK一样简单,但是你会在插件上重复数据 - 你可能需要代理自动编号PK并用UNIQUE CONSTRAINT强制执行唯一性。