外键上的外键 - SQL 服务器

Foreign key on a Foreign key - SQL Server

我正在为一个项目创建一个数据库,为了检查约束,我需要在另一个外键上声明一个外键。

我有一个 Person table 和一个 Groups table,它们都包含一个 DepartmentID。每当我在 Task table 中插入新任务时,我想检查 Groups.DepartmentID 是否与 Person.DepartmentID.

匹配

这个想法是,一个任务与一个人相关联,并且有两种类型,一种定义其数据库工作、财务工作等的组类型,以及定义其维护、培训等的任务类型。当一个人试图添加一个 groupType 不适用于 his/her 部门的任务,它应该会失败。

我尝试将这些属性作为外键添加到 Task table,但是 Microsoft 不接受在非唯一或非主键上声明外键 SQL 服务器(PersonGroup table 中的 DepartmentID 不能是唯一的!)。

有人知道如何解决这个问题吗?

CREATE TABLE Department 
(
    ID int PRIMARY KEY IDENTITY,
    Name varchar(50),
    UNIQUE ("Name")
)

CREATE TABLE Groups
(
    ID int IDENTITY,
    GroupType varchar(50) PRIMARY KEY,
    Description varchar(255) DEFAULT ('-'),
    DepartmentID int 
        FOREIGN KEY (DepartmentID) REFERENCES Department(ID),
)

CREATE TABLE Person 
(
    ID int PRIMARY KEY IDENTITY,
    Name varchar(50),
    DepartmentID int 
         FOREIGN KEY (DepartmentID) REFERENCES Department(ID)
)

CREATE TABLE TaskType
(
    ID int IDENTITY,
    TaskType varchar(50) PRIMARY KEY,
    Description varchar(255) DEFAULT ('-'), 
)

CREATE TABLE Task
(
    ID int IDENTITY,
    TimeFrame decimal(4,2),
    Yearcount int,
    GroupType varchar(50),
    TaskType varchar(50), 
    WeekNr int,
    ExceptionDetail varchar(255) DEFAULT ('-'),
    PersonID int
)

这些是任务 table 中不被接受的 FK 属性:

GDID int FOREIGN KEY REFERENCES Groups(DepartmentID),
PDID int FOREIGN KEY REFERENCES Person(DepartmentID),
CHECK (GDID = PDID),    

UNIQUE ("TaskType", "GroupType", "WeekNr", "Yearcount"),
FOREIGN KEY (TaskType) REFERENCES TaskType(TaskType),
FOREIGN KEY (PersonID) REFERENCES Person(ID),
FOREIGN KEY (GroupType) REFERENCES Groups(GroupType)

向这些包含主键 附加列 1 的表添加更宽的 "super keys",然后声明外键使用它们。是否也删除多余的较小外键是个人喜好问题:

CREATE TABLE Groups(
ID int IDENTITY,
GroupType varchar(50) PRIMARY KEY,
Description varchar(255) DEFAULT ('-'),
DepartmentID int FOREIGN KEY (DepartmentID) REFERENCES Department(ID),
constraint Group_Dep_XRef UNIQUE (GroupType,DepartmentID)
)

CREATE TABLE Person(
ID int PRIMARY KEY IDENTITY,
Name varchar(50),
DepartmentID int FOREIGN KEY (DepartmentID) REFERENCES Department(ID),
constraint Person_Dept_XRef UNIQUE (ID,DepartmentID)
)

CREATE TABLE Task(
ID int IDENTITY,
TimeFrame decimal(4,2),
Yearcount int,
GroupType varchar(50),
TaskType varchar(50), 
WeekNr int,
ExceptionDetail varchar(255) DEFAULT ('-'),
PersonID int,
DepartmentID int,
constraint FK_Group_Dept_XRef FOREIGN KEY (GroupType,DepartmentID)
        references Group (GroupType,DepartmentID),
constraint FK_Person_Dept_XRef FOREIGN KEY (PersonID,DepartmentID)
        references Person (ID,DepartmentID),
UNIQUE ("TaskType", "GroupType", "WeekNr", "Yearcount"),
FOREIGN KEY (TaskType) REFERENCES TaskType(TaskType),
FOREIGN KEY (PersonID) REFERENCES Person(ID), --Redundant now
FOREIGN KEY (GroupType) REFERENCES Groups(GroupType) --Also redundant
)

(我还将 GDIDPDID 合并为 DepartmentID - 如果它们总是相等的,为什么要存储两次然后必须有另一个约束来断言他们平等吗?)


1如果主键(或唯一键)足以唯一标识每一行,则包含键列 和 [=25 的任何更宽的键=] 额外的列也必须足以唯一标识每一行。