与辅助表的SQL关系,而无需添加重复的列

时间:2018-09-06 13:41:41

标签: sql sql-server foreign-keys constraints relationship

有城市,工作类型和任务。城市可以有多种工作类型。为可以具有多个作业类型的城市创建任务。城市可以有许多任务。但是,在为分配给城市的任务添加任务类型时,必须确保城市具有该任务类型。

在添加/更新Task_JobTypes时如何创建关系/约束,以确保与任务关联的城市在City_JobTypes中具有允许的工作类型?必须在Task_JobTypes“ FK_Task_JobTypes_JobTypes”中约束而不是JobTypes。

城市-ID,名称

JobTypes-ID,名称

CityJobTypes-CityId,JobTypeId(每个城市允许的作业类型)

任务-ID,城市ID,名称(城市任务)

TaskJobTypes-TaskId,JobTypeId(每个任务的Jobbs类型)

表格-

CREATE TABLE [dbo].[Cities](
    [Id] [int] IDENTITY(1,1) NOT NULL,  
    [Name] [varchar](500) NOT NULL, 
CONSTRAINT [PK_Cities] PRIMARY KEY CLUSTERED ([Id] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO    

CREATE TABLE [dbo].[JobTypes](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [varchar](50) NOT NULL
 CONSTRAINT [PK_JobTypes] PRIMARY KEY CLUSTERED ([Id] ASC)
 WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO    

CREATE TABLE [dbo].[City_JobTypes](
    [JobTypeId] [int] NOT NULL,
    [CityId] [int] NOT NULL
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[City_JobTypes]  WITH CHECK ADD  CONSTRAINT [FK_City_JobTypes_Cities] FOREIGN KEY([CityId])
REFERENCES [dbo].[Cities] ([Id])
GO    

ALTER TABLE [dbo].[City_JobTypes]  WITH CHECK ADD  CONSTRAINT [FK_City_JobTypes_JobTypes] FOREIGN KEY([JobTypeId])
REFERENCES [dbo].[JobTypes] ([Id])
GO 

CREATE TABLE [dbo].[Tasks](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [CityId] [int] NOT NULL,
    [Name] [varchar](50) NOT NULL,
 CONSTRAINT [PK_Tasks] PRIMARY KEY CLUSTERED ([Id] ASC)
 WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Tasks]  WITH CHECK ADD  CONSTRAINT [FK_Tasks_Cities] FOREIGN KEY([CityId])
REFERENCES [dbo].[Cities] ([Id])
GO

CREATE TABLE [dbo].[Task_JobTypes](
    [TaskId] [int] NOT NULL,
    [JobTypeId] [int] NOT NULL,
 CONSTRAINT [IX_Task_JobTypes-TaskId,JobTypeId] UNIQUE NONCLUSTERED 
(
    [TaskId] ASC,
    [JobTypeId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Task_JobTypes]  WITH CHECK ADD  CONSTRAINT [FK_Task_JobTypes_JobTypes] FOREIGN KEY([JobTypeId])
REFERENCES [dbo].[JobTypes] ([Id])
GO

ALTER TABLE [dbo].[Task_JobTypes]  WITH CHECK ADD  CONSTRAINT [FK_Task_JobTypes_Tasks] FOREIGN KEY([TaskId])
REFERENCES [dbo].[Tasks] ([Id])
GO

2 个答案:

答案 0 :(得分:0)

  

添加/更新时如何创建关系/约束   Task_JobTypes,以确保与任务关联的城市具有   City_JobTypes中允许的职位类型?

您可以使用CHECK CONSTRAINT来调用函数。该函数将TaskIDJobTypeID作为参数,并查询连接到Tasks表的City_JobTypes表以查看City是否具有那个{{1 }}。然后,如果城市具有职位类型,该函数将返回True JobType,否则返回false (1)

或者,您也可以使用TRIGGER进行此操作,但我更喜欢亲自检查约束。

答案 1 :(得分:0)

在我看来,您在哲学上反对composite keys。链接表City_JobTypes的复合主键为CityId, JobTypeId。约束City_JobTypes的任何其他表都需要约束其主键。碰巧是两列,但仍然是一个键。我看不到那里的问题。


我看你的结构的方式是...

Task属于单个City,并且具有单个JobType

由于作业必须具有一个 City一个 JobType,因此要设置Task的那些属性吗?

City
 ↑
Task → JobType


一个City也有0 ..许多JobTypes被“允许”。

City ← City_JobTypes
 ↑          ↓
Task → JobType


这时您的Task表已经有一个CityID和一个JobTypeID

为什么不针对City_JobTypes表约束该组合键?

City ← City_JobTypes
 ↑   ↗      ↓
Task → JobType


如果单个Task实际上可以有0 ..许多JobTypes ...

我将从这里开始,我没有看到可以基于Tasks链接来限制City_JobType的任何方式...

City ← City_JobTypes↘
 ↑                   JobType
Task ← Task_JobTypes↗

然后,我决定可以合理地将Task标识为具有复合主键的CityTask。这将允许以下操作。

   City  ←    City_JobTypes ↘
   ↑          ↑     ↑        JobType
CityTask ← CityTask_JobTypes↗