【问题标题】:One-to-many relationship using same SQL table使用同一个 SQL 表的一对多关系
【发布时间】:2010-02-01 05:20:48
【问题描述】:

我正在设计我的数据库和其中一个表(任务),需要能够与其自身建立一对多的关系。这是因为一个任务可以有多个具有相同数据的子任务(很像 SO 上的问答)。

由于我的SQL不是很强大,我只是有点困惑,关于如何在同一张表上进行一对多。

目前我有这些行:

TaskId(唯一标识符)
aspnet_OwnerUserId(唯一标识符)
标题 (nvarchar(50)) 说明 (nvarchar(MAX))
开始日期 (smalldatetime)
DueDate (smalldatetime)

【问题讨论】:

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


    【解决方案1】:

    虽然我不太确定您要实现什么,但根据您作为表格字段提供的内容,我认为与表格本身的一对多关系更合适。

    TaskId (integer *Primary Key)
    Ref_Id (integer *Foreign Key references to TaskId above)
    ASPNet_OwnerUserId (integer)
    Title (varchar/text)
    StartDate (Date/Timestamp)
    DueDate (Date/Timestamp)
    

    如果你想让一个子任务有多个父任务,那么请忘记我所说的。也就是说,可以对某个问题做出一个或多个答案,但不能反过来。

    编辑: 我想您将有另一个表“aspnet_OwnerUser”,其中包含一些用户信息。如果是这种情况,请查看以下 SQL。否则,算了。 ;)

    CREATE TABLE `aspnet_OwnerUser`
    (
        `id` SERIAL PRIMARY KEY
        , `name` VARCHAR(128)
        -- further detail follows
    );
    
    CREATE TABLE `task`
    (
        `id` SERIAL PRIMARY KEY
        , `ref_id` INTEGER
            CONSTRAINT REFERENCES `task`(`id`)
        , `aspnet_OwnerUserId` INTEGER
            CONSTRAINT REFERENCES `aspnet_OwnerUser`(`id`)
        , `title` VARCHAR(128) NOT NULL
        , `startdate` TIMESTAMP
        , `duedate` TIMESTAMP
    );
    

    附言以上 SQL 是为 PostgreSQL 编写的,对于其他 DBMS,请随意更改。

    【讨论】:

    • 是的,看起来我更像是一个白痴,它第一次出现并且一对多正是我的想法。我似乎无法通过大脑翻译那个。更新问题。
    • 感谢您让我的大脑恢复正常。 /鞠躬
    【解决方案2】:

    交集(联结)表的编码与您预期的差不多,只有两个外键指向同一个表。

    create table task_subtasks
     ( master_id number not null
       , sub_id number not null
       , constraint task_subtask_pk primary key (master_id, sub_id)
        , constraint task_subtask_master_fk foreign key (master_id)
             references tasks (taskid)
        , constraint task_subtask_sub_fk foreign key (sub_id)
             references tasks (taskid)
        )
    /
    

    编辑

    输入完之后,我想询问您的数据模型。我可以看到一个任务可以拥有许多子任务,但我不确定一个子任务如何属于许多主任务。你确定你真的不想要一对多的关系吗?

    编辑 2

    在我编写该编辑时,我看到您编辑了您的问题以回答这一点。

    create table tasks (
    TaskId number not null
    , aspnet_OwnerUserId number not null
    , subTaskId number
    , Title (nvarchar(50))
    , Description (nvarchar(MAX))
    , StartDate (smalldatetime)
    , DueDate (smalldatetime)
    , constraint task_pk primary key (taskid)
    , constraint sub_task_fk foreign key (subtaskid)
        references tasks (taskid)
    )
    /
    

    【讨论】:

    • 这是多对多的正确答案。感谢shinkou,我已经得到纠正。
    • @Alastair Pitts - 在这个网站上,判断给定的数据模型是真正的目标还是只是一个简化的测试用例并不总是那么容易。
    【解决方案3】:

    如果您的类比类似于关于 SO 的问答,那么这不是多对多关系,而是一对多关系。一个问题可能有多个答案,但一个答案只属于一个问题。最简单的映射方法是:

    表格 - 任务

    TaskID uniqueidentifier NOT NULL,
    ParentTaskID uniqueidentifier NULL,
    (other fields)
    

    然后创建一个从ParentTaskIDTaskID 的自引用外键约束。

    假设由于某种原因您确实需要 M:M 映射。这必须使用映射表来完成;自引用 M:M 与涉及两个表的 M:M 并没有什么不同:

    表格 - 任务

    TaskID uniqueidentifier NOT NULL,
    (other fields)
    

    表格 - 子任务

    TaskID uniqueidentifier NOT NULL,
    SubTaskID uniqueidentifier NOT NULL
    

    在引用Tasks (TaskID) 列的SubTasks 表中对TaskIDSubTaskID 放置外键约束。这与任何其他 M:M 关系之间的唯一区别是两个外键约束都指向同一个表(在某些 DBMS 上,您将无法级联它们)。

    【讨论】:

    • 对我的原始问题和更新的更正问题都有很好的答案:)
    【解决方案4】:

    好吧,您可以以多对多的方式执行此操作,但实际上它更像是nested set

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-17
      • 2018-07-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多