Rod*_*phe 7 sql data-integrity user-defined-functions check-constraint
我有以下(虚构)表:
?????????????????????? ??????????????????????
? Course ? ? Person ?
?????????????????????? ??????????????????????
? ID ? int ? ? ID ? int ?
? Name ? varchar(50) ? ? Name ? varchar(50) ?
?????????????????????? ??????????????????????
?????????????????????? ???????????????????????
? Occupation ? ? B_Occupation_Person ?
?????????????????????? ???????????????????????
? ID ? int ? ? Person_ID ? int ?
? Name ? varchar(50) ? ? Ocupation_ID ? int ?
?????????????????????? ???????????????????????
???????????????????
? B_Course_Person ?
???????????????????
? Course_ID ? int ?
? Person_ID ? int ?
???????????????????
Run Code Online (Sandbox Code Playgroud)
在Occupation表中,有2行:Student和Teacher.
该B_Occupation_Person绑定表让我给所有的人的职业和B_Course_Person绑定表让我一个老师与课程相关联.
我的问题是我想确保B_Course_Person只能包含教师.
我的第一个想法是在这个表上添加一个检查约束,但我只能通过使用UDF来从B_Occupation_Person表中获取该人的职业.从我在这里读到的内容来看,在检查约束中使用UDF是不好的.
我的第二个想法是Occupation在B_Course_Person表中添加一列,但后来我得到了数据冗余......
什么是最好的方式,在这里?
谢谢,
小智 1
如果您的人员表中有一个“类型”列来区分学生和教师(例如,如果一个人可以同时是两者,则这是不可能的)您可以在主键中包含该类型列,然后限制链接表的外键各位老师:
create table person
(
id integer not null,
person_type varchar(10) not null,
name varchar(100),
constraint pk_person primary key (id, person_type),
constraint type_check check (person_type in ('student', 'teacher'))
);
create table b_occupation_person
(
occupation_id integer not null,
person_id integer not null,
person_type varchar(10) not null,
constraint fk_occupation_person
foreign key (person_id, person_type)
references person (id, person_type),
constraint type_check check (person_type = 'teacher')
);
Run Code Online (Sandbox Code Playgroud)
这person_type是多余的,b_occupation_person但据我所知,这是以声明方式创建此类约束的唯一选择。
由于外键和检查约束,除了教师之外不可能插入任何其他内容 b_occupation_person。
但再次强调:只有当你真正能够区分教师和学生(并且教师不能是学生)时,这才有效。
如果您需要一个人作为老师和学生(并且您没有“person_type”),您可能会考虑一个teacher仅引用 person 表的表:
create table person
(
id integer not null primary key,
name varchar(100)
);
create table teacher
(
person_id integer not null primary key,
foreign key (person_id) references person (id)
);
create table b_occupation_person
(
occupation_id integer not null,
teacher_id integer not null,
foreign key (teacher_id) references teacher (person_id)
);
Run Code Online (Sandbox Code Playgroud)
这样做的缺点是作为老师的人需要插入两次(一次插入人,一次插入老师)。
在 PostgreSQL 中,您可以利用表继承并定义 Teacher 从 person 继承。因此,对教师的任何插入也会自动创建一个人(因此您不需要两次插入这样的人)。