多对多关系表的约束-两个相关记录都需要引用相同的从属记录?

时间:2019-05-27 19:48:00

标签: sql sql-server

存在三个实体,StudentClassDepartment。部门和学生之间存在一对多关系。部门和班级也有一对多的关系。学生和班级之间存在多对多关系。

create table Department 
(
    Id int primary key,
    -- ...
)

create table Student 
(
    Id int primary key, 
    DepartmentId int not null references Department(Id), 
    -- ....
)

create table Class 
(
    Id int primary key, 
    DepartmentId int not null references Department(Id), 
    ....
)

下表是学生和班级之间的多对多关系。现在,用户可以在表中放入来自不同(不应允许)部门的一对学生/班级。除了使用触发器之外,还有其他方法可以防止它吗?

create table StudentAndClass 
(
    StudentId int references Student(Id), 
    ClassId int references Class(Id), 
    -- ....
    primary key (StudentId, ClassId)
)

2 个答案:

答案 0 :(得分:2)

您应该使用“检查约束”

CREATE FUNCTION dbo.CheckDepartment()
RETURNS int
AS BEGIN RETURN (
SELECT count(1)
    FROM StudentAndClass sc
    JOIN Student s on sc.StudentId=s.id
    JOIN Class c on sc.ClassId=c.id
WHERE c.DepartmentId<>s.DepartmentId
) END
go

ALTER TABLE StudentAndClass ADD CONSTRAINT chkDep CHECK (dbo.CheckDepartment() = 0);

这将确保部门匹配

答案 1 :(得分:2)

您可以在没有触发器或特殊功能的情况下执行此操作。这个想法是使用外键关系。 。 。通过定义一组额外的键并将DepartmentId(冗余)添加到联结表:

create table Students (
    StudentId int primary key, 
    DepartmentId int not null references Department(Id), 
    -- ....
    unique (DepartmentId, StudentId)
);

create table Classes (
    ClassId int primary key, 
    DepartmentId int not null references Department(Id), 
    ....
    unique (DepartmentId, ClassId)
);

create table StudentClasses (
    DepartmentId int references Department(DepartmentId),
    StudentId int, 
    ClassId int, 
    -- ....
    primary key (StudentId, ClassId),
    foreign key (DepartmentId, StudentId) references (DepartmentId, StudentId),
    foreign key (DepartmentId, ClassId) references (DepartmentId, ClassId),
);

您可能不需要冗余,但是可能没有触发器或特殊功能。