123 4NF

Informally, Fourth Normal Form, or 4NF, says that independent multi-valued facts should not be combined into one relation merely because they concern the same key.

Example which violates 4NF

The following relation records the skills and languages known by a student:

StudentCapability
Alice,Logic,English Alice,Logic,French Alice,Databases,English Alice,Databases,French Bob,Databases,English

Assume the following multi-valued dependencies hold. Here ↠ denotes a multi-valued dependency:

  • {student} ↠ {skill} because each student has a set of skills
  • {student} ↠ {language} because each student has a set of languages

For a given student, the skills and languages are independent many-valued facts. The rows for Alice contain every combination of her skills and languages, even though knowing Logic and speaking French are separate facts. The same modelling mistake can be written in Predica:


entity StudentCapability
{
    String student;
    String skill;
    String language;

    key {student, skill, language};
}

Here the independent many-valued facts have been combined into one entity type.

Writing the dependency as a constraint

If the model is left in this shape, the multi-valued dependencies have to be imposed over the containing collection of capability records. One way to write the constraint is to say that for any two rows for the same student, the recombined row must also exist:


entity School
{
    StudentCapability capability*;

    constraints
    {
        capability.(student, skill, language).Σ =
        (
            capability.(student, skill)
            ⊓ capability.(student, language)
        ).Σ;
    }
}

This constraint says that the stored StudentCapability records must be closed under recombining skills and languages for the same student. The equality says that the stored ternary relation is exactly the join of its two binary projections. It is non-local because the representation stores a Cartesian product of independent facts instead of storing each student's skills and languages as separate predicate extensions.

Fixing the violation

The fix is to represent the two independent many-valued facts separately. In relational form, this decomposes the original relation into two relations:

StudentSkill
Alice,Logic Alice,Databases Bob,Databases
StudentLanguage
Alice,English Alice,French Bob,English

In Predica, the same repair is to give the student two separate attributes with many-valued extensions:


entity Student
{
    String name;
    String skill*;
    String language*;

    key {name};
}

entity School
{
    Student student*;
}

The attributes skill and language still have singular types. Their multiplicity is represented by separate attribute extensions, so Predica does not need to manufacture the Cartesian product of skills and languages.

This repair is different from the 2NF, 3NF, and BCNF examples. There the problem was a fact stored too high up, and the fix was to introduce a more specific domain. Here the problem is an unnecessary combination of independent many-valued facts. The fix is to keep those facts as separate attributes of their common subject.

This is one of the places where Predica's treatment of attribute extensions is especially useful. Independent multiplicities can remain independent predicates. They do not have to be forced into a combined relation unless the combinations themselves are meaningful facts.