I have the following (fictitious) tables:
╔════════════════════╗ ╔════════════════════╗
║ 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 ║
╚═══════════╩═════╝
In the Occupation
table, there are 2 rows: Student
and Teacher
.
The B_Occupation_Person
binding table allows me to give all the persons an occupation and the B_Course_Person
binding table allows me to associate a teacher with a course.
My problem is I'd like to ensure that B_Course_Person
could only contain teachers.
My first idea was to add a check constraint on this table but I can only do it by using a UDF to get the person's occupation from the B_Occupation_Person
table. And from what I read here, it's bad to use a UDF in a check constraint.
My second idea was to add a column Occupation
in the B_Course_Person
table but then I get data redundancy...
What's the best way, here?
Thanks,
CHECK constraints reject values that evaluate to FALSE. Because null values evaluate to UNKNOWN, their presence in expressions may override a constraint.
Use the view table_constraints in the information_schema schema. The column table_name gives you the name of the table in which the constraint is defined, and the column constraint_name contains the name of the constraint.
Using SQL Server Management Studio Open the Table Designer for the table containing the foreign key you want to view, right-click in the Table Designer, and choose Relationships from the shortcut menu. In the Foreign Key Relationships dialog box, select the relationship with properties you want to view.
Use SQL Server Management Studio In Object Explorer, expand the table to which you want to add a check constraint, right-click Constraints and select New Constraint. In the Check Constraints dialog box, select in the Expression field and then select the ellipses (...).
If you have a "type" column in your person table to distinguish students from teachers (which is e.g. not possible if a person can be both) you can include that type column in the primary key, and then restrict the foreign key the link table to teachers:
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')
);
The person_type
is redundant in the b_occupation_person
but as far as I can tell it's the only option to create this type of constraint in a declarative manner.
Due to the foreign key and the check constraint it's not possible to insert anything else but a teacher into b_occupation_person
.
But again: this only works if you actually can distinguish teachers from students (and if a teacher cannot be a student).
If you need a person to be teacher and student (and you don't have a "person_type"), you might think about a teacher
table that simply references the person table:
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)
);
The drawback of this is that a person that is teacher needs to be inserted twice (once into person, once into teacher).
In PostgreSQL you could take advantage of table inheritance and define teacher to inherit from person. Thus any insert into teacher would automatically create a person as well (so you don't need to insert such a person twice).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With