'How to use constraints to force two child items be from the same parent?

  • I have a Jobs table that holds jobs.
  • I have a Tasks table that holds tasks that belong to a job (1:many).
  • I have a Task_Relationships table that holds the data about which tasks depend on other tasks within a job.

enter image description here

I have 2 jobs, each job has 3 tasks and within the jobs the tasks are related as in the diagram. The Task_Relationships table is to represent that tasks within a job have dependencies between them.

How to ensure that when I add an entry to the Task_Relationships table say (1,2) representing the fact that task 1 is related to task 2, that tasks 1 and 2 are in the same job? I'm trying to enforce this through keys and not through code.

enter image description here

drop table if exists dbo.test_jobs
create table dbo.test_jobs (
    [Id] int identity(1,1) primary key not null,
    [Name] varchar(128) not null
)

drop table if exists dbo.test_tasks  
create table dbo.test_tasks (
    [Id] int identity(1,1) primary key not null,
    [Job_Id] int not null,
    [Name] varchar(128) not null
    constraint fk_jobs foreign key ([Id]) references dbo.test_jobs(Id)
)

drop table if exists dbo.test_task_relationships 
create table dbo.test_task_relationships (
    [Id] int identity(1,1) not null,
    [From_Task] int not null,
    [To_Task] int not null
    constraint fk_tasks_from foreign key ([From_Task]) references dbo.test_tasks(Id),
    constraint fk_tasks_to foreign key ([To_Task]) references dbo.test_tasks(Id)
)


Solution 1:[1]

A reliance on identity columns as primary keys is not helping you here. And it is a logic fault to use an identity column in the relationship table IMO. Surely you do not intend to allow multiple rows to exist in that table with the same values for <from_task, to_task>.

Imagine the child table defined as:

create table dbo.test_tasks (
    Job_Id int not null,
    Task_Id tinyint not null,
    Name varchar(128) not null,
    constraint pk_tasks primary key clustered (Job_Id, Task_Id),
    constraint fk_jobs foreign key ([Job_Id]) references dbo.test_jobs(Id)
);

Now your relationship table can be transformed into:

create table dbo.test_task_relationships (
    From_Job int not null,
    From_Task tinyint not null,
    To_Job int not null,
    To_Task tinyint not null
);

I'll leave it to you to complete the DDL but that should make your goal trivial.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 SMor