代码之家  ›  专栏  ›  技术社区  ›  Alastair Pitts

使用同一个SQL表的一对多关系

  •  2
  • Alastair Pitts  · 技术社区  · 15 年前

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

    我只是有点困惑,因为我的SQL不是很强,关于如何在同一个表上生成一对多。

    当前我有以下行:

    任务ID(唯一标识符)
    aspnet所有者userid(唯一标识符)
    标题(nvarchar(50)) 说明(nvarchar(max))
    开始日期(smalldatetime)
    DueDate(小日期时间)

    4 回复  |  直到 8 年前
        1
  •  4
  •   shinkou    15 年前

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

    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
    );
    

    P.S.以上SQL是为PostgreSQL编写的,其他DBMS请随意修改。

        2
  •  3
  •   APC    15 年前

    交叉点(交叉点)表的编码与您期望的差不多,只是有两个外键指向同一个表。

    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)
    )
    /
    
        3
  •  2
  •   Aaronaught    15 年前

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

    表任务

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

    然后从中创建自引用外键约束 ParentTaskID TaskID .

    假设出于某种原因,您确实需要m:m映射。这需要使用一个映射表来完成;自引用m:m与包含两个表的m:m没有什么不同:

    表任务

    TaskID uniqueidentifier NOT NULL,
    (other fields)
    

    表-子任务

    TaskID uniqueidentifier NOT NULL,
    SubTaskID uniqueidentifier NOT NULL
    

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

        4
  •  1
  •   prodigitalson    15 年前

    你可以对很多人这样做,但实际上更像是 nested set .