122 BCNF

Informally, Boyce-Codd Normal Form, or BCNF, says that whenever a set of attributes determines some other attribute, that determinant should be a superkey.

Example which violates BCNF

The following relation records the lecturer for each student's course enrolment:

CourseEnrolment
Alice,Logic,Prof Gray Alice,Databases,Prof Chen Bob,Logic,Prof Gray Bob,Databases,Prof Chen

Assume the following functional dependencies hold:

  • {student, course} → {lecturer} because a student's enrolment in a course has one lecturer
  • {lecturer} → {course} because each lecturer teaches exactly one course

The second dependency is visible in the repeated lecturer-course pairs. It violates BCNF because lecturer is not a superkey, yet {lecturer} → {course} holds. It can still satisfy 3NF because course is part of a candidate key: {student, lecturer} also determines all attributes.


entity CourseEnrolment
{
    String student;
    String course;
    String lecturer;

    key {student, course};
    key {student, lecturer};
}

Here course is a fact about the lecturer, but it is stored on CourseEnrolment.

Writing the dependency as a constraint

If the model is left in this shape, the dependency from lecturer to course has to be imposed over the containing collection of enrolments. One way to write it is to say that there is no pair of enrolments with the same lecturer and different courses:


entity University
{
    CourseEnrolment enrolment*;

    constraints
    {
        let university = this in
            enrolment.(let e = this in
                university.enrolment.[
                    lecturer = e.lecturer
                    ∧ course ≠ e.course
                ].Σempty);
    }
}

This constraint is the Predica form of {lecturer} → {course}. It is non-local because the course taught by a lecturer is repeated on enrolment records instead of being a local fact about a lecturer.

Fixing the violation

The fix is to separate the fact about the lecturer's course from the fact that a student is enrolled with a lecturer. In relational form, this decomposes the original relation into two relations:

CourseEnrolment
Alice,Prof Gray Alice,Prof Chen Bob,Prof Gray Bob,Prof Chen
Lecturer
Prof Gray,Logic Prof Chen,Databases

In Predica, the same repair is to model Lecturer explicitly:


entity Lecturer
{
    String name;
    String course;

    key {name};
}

entity CourseEnrolment
{
    String student;
    Lecturer lecturer;

    key {student, lecturer};
}

entity University
{
    Lecturer lecturer*;
    CourseEnrolment enrolment*;
}

After this repair, the cross-enrolment FD constraint is no longer needed. The course is a local attribute of Lecturer, and each enrolment points to the lecturer responsible for that enrolment.