7

我有以下(虚构的)表格:

╔════════════════════╗        ╔════════════════════╗
║ 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 ║
╚═══════════╩═════╝

Occupation表中,有 2 行:StudentTeacher

绑定表B_Occupation_Person允许我给所有人一个职业,B_Course_Person绑定表允许我将老师与课程联系起来。

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

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

我的第二个想法是OccupationB_Course_Person表中添加一列,但随后我得到了数据冗余......

什么是最好的方法,在这里?

谢谢,

4

2 回答 2

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')
);

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)
);

这样做的缺点是需要插入两次作为老师的人(一次插入人,一次插入老师)。

在 PostgreSQL 中,您可以利用表继承并将教师定义为从人继承。因此,任何插入到教师中的操作也会自动创建一个人(因此您不需要两次插入这样的人)。

于 2012-08-27T18:26:12.457 回答
0

您在这里的问题代表了一种业务逻辑形式。您不仅要确保 b_course_person 在插入时仅包含教师,而且还要确保数据保持一致 - 即:如果一个人不再成为教师,那么 b_course_person 中的数据会发生什么情况?

因此,您应该在代码中实现此逻辑;或者作为一个存储过程来表示您与数据库的接口并确保所有数据更改都会产生一致、有效的数据集,或者作为业务逻辑层中应用程序层的更上层。

于 2012-08-27T17:19:42.373 回答