没有UDF的SQL检查约束

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行:StudentTeacher.

B_Occupation_Person绑定表让我给所有的人的职业和B_Course_Person绑定表让我一个老师与课程相关联.

我的问题是我想确保B_Course_Person只能包含教师.

我的第一个想法是在这个表上添加一个检查约束,但我只能通过使用UDF来从B_Occupation_Person表中获取该人的职业.从我在这里读到的内容来看,在检查约束中使用UDF是不好的.

我的第二个想法是OccupationB_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 继承。因此,对教师的任何插入也会自动创建一个人(因此您不需要两次插入这样的人)。