如何使用约束强制两个子项来自同一父项?
How to use constraints to force two child items be from the same parent?
- 我有一个职位 table 有职位。
- 我有一个 Tasks table 包含属于作业的任务 (1:many)。
- 我有一个 Task_Relationships table 保存关于哪些任务依赖于作业中其他任务的数据。
我有 2 个作业,每个作业有 3 个任务,并且在作业中任务是相关的,如图所示。 Task_Relationships table 表示作业中的任务之间存在依赖关系。
如何确保当我向 Task_Relationships 添加条目时 table say (1,2) 代表任务 1 与任务 2 相关的事实,任务 1 和 2 是在同一份工作?我试图通过键而不是代码来强制执行此操作。
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)
)
依赖标识列作为主键对您没有帮助。在关系 table IMO 中使用标识列是逻辑错误。当然,您不打算允许多个行存在于 table 中,并且 .
具有相同的值
假设 child table 定义为:
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)
);
现在你们的关系table可以转化为:
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
);
我会把它留给你来完成 DDL,但这应该会使你的目标微不足道。
您可以在 Task
table 中声明一个超级键,其中包括 Job_Id
列以及现有键中的列。
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),
constraint UQ_Tasks_WithJob UNIQUE (Id, Job_Id)
)
然后您可以将 Job_Id
列添加到关系 table 并将其包含在两个外键约束中:
create table dbo.test_task_relationships (
[Id] int identity(1,1) not null,
[From_Task] int not null,
Job_Id int not null,
[To_Task] int not null
constraint fk_tasks_from foreign key ([From_Task], Job_Id) references dbo.test_tasks(Id, Job_Id),
constraint fk_tasks_to foreign key ([To_Task], Job_Id) references dbo.test_tasks(Id, Job_Id)
)
table 现在无法包含不匹配的任务。如有必要,如果您不想将 job_id 列的存在暴露给应用程序并在插入期间自动填充它,请将此 table 包装在 view/trigger 中。
- 我有一个职位 table 有职位。
- 我有一个 Tasks table 包含属于作业的任务 (1:many)。
- 我有一个 Task_Relationships table 保存关于哪些任务依赖于作业中其他任务的数据。
我有 2 个作业,每个作业有 3 个任务,并且在作业中任务是相关的,如图所示。 Task_Relationships table 表示作业中的任务之间存在依赖关系。
如何确保当我向 Task_Relationships 添加条目时 table say (1,2) 代表任务 1 与任务 2 相关的事实,任务 1 和 2 是在同一份工作?我试图通过键而不是代码来强制执行此操作。
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)
)
依赖标识列作为主键对您没有帮助。在关系 table IMO 中使用标识列是逻辑错误。当然,您不打算允许多个行存在于 table 中,并且
假设 child table 定义为:
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)
);
现在你们的关系table可以转化为:
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
);
我会把它留给你来完成 DDL,但这应该会使你的目标微不足道。
您可以在 Task
table 中声明一个超级键,其中包括 Job_Id
列以及现有键中的列。
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),
constraint UQ_Tasks_WithJob UNIQUE (Id, Job_Id)
)
然后您可以将 Job_Id
列添加到关系 table 并将其包含在两个外键约束中:
create table dbo.test_task_relationships (
[Id] int identity(1,1) not null,
[From_Task] int not null,
Job_Id int not null,
[To_Task] int not null
constraint fk_tasks_from foreign key ([From_Task], Job_Id) references dbo.test_tasks(Id, Job_Id),
constraint fk_tasks_to foreign key ([To_Task], Job_Id) references dbo.test_tasks(Id, Job_Id)
)
table 现在无法包含不匹配的任务。如有必要,如果您不想将 job_id 列的存在暴露给应用程序并在插入期间自动填充它,请将此 table 包装在 view/trigger 中。