Loading learning content...
Identifying 3NF violations is only half the battle—we need a systematic way to fix them. The 3NF Synthesis Algorithm (also known as the Bernstein Algorithm or the 3NF Decomposition Algorithm) provides a guaranteed method for decomposing any relation schema into Third Normal Form.
Unlike ad-hoc decomposition approaches, this algorithm provides dual guarantees: the resulting decomposition is both lossless (no information is lost when joining the decomposed relations) and dependency-preserving (all original functional dependencies can be verified within individual relations). These guarantees make the algorithm the gold standard for 3NF decomposition.
By the end of this page, you will master the complete 3NF synthesis algorithm, understand why each step is necessary, and be able to apply it to any relation with any set of functional dependencies. You'll also understand the theoretical guarantees that make this algorithm reliable.
Before diving into the mechanics, let's understand what the 3NF synthesis algorithm accomplishes and why it works.
Algorithm Guarantees:
Given any relation R with functional dependencies F, the 3NF synthesis algorithm produces a decomposition {R₁, R₂, ..., Rₖ} such that:
- Each Rᵢ is in Third Normal Form
- The decomposition is lossless-join (R = R₁ ⋈ R₂ ⋈ ... ⋈ Rₖ)
- The decomposition is dependency-preserving (F ⊆ (F₁ ∪ F₂ ∪ ... ∪ Fₖ)⁺)
No other decomposition method for 3NF provides all three guarantees simultaneously. BCNF decomposition, by contrast, cannot always preserve dependencies.
| Property | Guarantee | Why It Matters |
|---|---|---|
| 3NF Achieved | Every resulting relation satisfies 3NF | Eliminates transitive dependencies on non-prime attributes |
| Lossless Join | Join of all Rᵢ reproduces original R exactly | No spurious tuples introduced; no data lost |
| Dependency Preservation | All FDs in F can be enforced locally | Constraints can be checked without joining relations |
| Polynomial Time | Algorithm runs in O(n²) time | Practical for real-world schemas |
High-Level Algorithm Structure:
Each step serves a specific purpose in achieving the guarantees. Let's examine each in detail.
Philip Bernstein developed this algorithm in 1976, proving that 3NF decomposition with both lossless join and dependency preservation is always achievable. This was a fundamental result in database theory, establishing 3NF as a practically optimal normal form.
The first step is to compute the canonical cover (also called minimal cover) of the functional dependencies. This eliminates redundancy in the FD set before decomposition.
Why This Matters:
Canonical Cover Algorithm:
123456789101112131415161718192021222324
ALGORITHM: Compute Canonical Cover Fc of F INPUT: Set of functional dependencies FOUTPUT: Canonical cover Fc 1. Set Fc = F 2. REPEAT until no changes: 2a. Combine FDs with same left side: Replace {X → A, X → B} with {X → AB} 2b. Remove extraneous left-side attributes: For each FD (X → A) in Fc: For each attribute B in X: If A ∈ (Fc with X→A replaced by (X-B)→A)⁺: Replace X → A with (X - B) → A 2c. Remove redundant FDs: For each FD (X → A) in Fc: If A ∈ (X)⁺ under (Fc - {X → A}): Remove X → A from Fc 3. RETURN FcThe canonical cover is not necessarily unique—different orderings of attribute removal can yield different but equivalent canonical covers. Any canonical cover works for 3NF synthesis; the result will be equivalent decompositions.
Once we have the canonical cover Fc, we create a relation for each FD. This is the heart of the synthesis algorithm.
The Core Insight:
If X → A is a functional dependency, then we should have a relation with attributes X ∪ {A} where X is the key.
This directly ensures that A depends on the key (X) and nothing but the key within that relation.
Relation Creation Rule:
12345678910111213
ALGORITHM: Create Relations from Canonical Cover INPUT: Canonical cover FcOUTPUT: Set of relation schemas D 1. Initialize D = ∅ 2. FOR each FD (X → Y) in Fc: Create relation schema Ri = X ∪ Y Designate X as the primary key of Ri Add Ri to D 3. RETURN DWhy This Guarantees Dependency Preservation:
Each FD X → Y becomes the key-to-nonkey relationship in its own relation. The FD can be verified by checking just that relation:
No joins required—each constraint is local to its dedicated relation.
If the canonical cover has multiple FDs with the same left side (e.g., A → B and A → C), they should be combined into a single relation (A, B, C with key A) rather than creating separate relations. This is typically handled in the canonical cover step by combining right sides.
The relations created from FDs might not include a candidate key of the original relation R. Without a candidate key relation, the decomposition might not be lossless. Step 3 ensures lossless join by adding a key relation if needed.
Why This Is Necessary:
Lossless join requires that we can reconstruct R from R₁ ⋈ R₂ ⋈ ... ⋈ Rₖ without spurious tuples. A sufficient condition (Chase test result) is that at least one Rᵢ contains a candidate key of R.
Key Presence Check:
123456789101112131415161718
ALGORITHM: Ensure Candidate Key Presence INPUT: Set of relation schemas D, Original relation R, FD set FOUTPUT: Updated D with key guarantee 1. Find a candidate key K of R (using F) 2. Check if any Ri in D contains K: FOR each Ri in D: If K ⊆ attributes(Ri): RETURN D // Key already present, done 3. If no Ri contains K: Create new relation Rk = K Designate K as the primary key of Rk Add Rk to D 4. RETURN DWhen Is the Key Relation Needed?
The key relation is typically needed when:
When Is It Already Present?
If R has multiple candidate keys, you only need to include ONE of them. Choose whichever is most natural for the application or simplest to represent. The lossless join property will be satisfied regardless of which candidate key is used.
The final step removes redundant relations—those whose attributes are entirely contained within another relation in the decomposition.
Why Remove Subsumed Relations?
Subsumption Removal:
123456789101112
ALGORITHM: Remove Subsumed Relations INPUT: Set of relation schemas DOUTPUT: Minimal set of relation schemas D' 1. Initialize D' = D 2. FOR each pair (Ri, Rj) in D' where i ≠ j: IF attributes(Ri) ⊆ attributes(Rj): Remove Ri from D' 3. RETURN D'Critical Insight: Why FDs Are Still Preserved
When R₂(B, C) is subsumed by R₁(A, B, C), the FD B → C is not lost:
Subsumption vs. Overlap:
Be careful to distinguish:
Only remove relations that are completely subsumed. If Rᵢ has even one attribute not in Rⱼ, keep both relations. Premature removal can lose attributes or dependencies.
Now let's put all the steps together into the complete algorithm:
3NF SYNTHESIS ALGORITHM (BERNSTEIN ALGORITHM)
12345678910111213141516171819202122232425262728293031323334353637
ALGORITHM: 3NF Synthesis (Bernstein Algorithm) INPUT: Universal relation R, Functional dependencies FOUTPUT: 3NF decomposition D with lossless join and dependency preservation //=== STEP 1: Compute Canonical Cover ===1. Compute canonical cover Fc of F: a. Combine FDs with same left side b. Remove extraneous left-side attributes c. Remove redundant FDs d. Repeat until no changes //=== STEP 2: Create Relations from FDs ===2. Initialize D = ∅3. FOR each FD (X → Y) in Fc: a. Create relation Ri = X ∪ Y b. Set primary key of Ri = X c. Add Ri to D //=== STEP 3: Ensure Candidate Key Presence ===4. Find a candidate key K of R using F5. IF no relation in D contains K: a. Create relation Rk = K b. Set primary key of Rk = K c. Add Rk to D //=== STEP 4: Remove Subsumed Relations ===6. FOR each pair (Ri, Rj) in D: IF attributes(Ri) ⊆ attributes(Rj): Remove Ri from D 7. RETURN D //=== GUARANTEES ===// - Every relation in D is in 3NF// - D is a lossless-join decomposition of R// - D preserves all dependencies in FThe 3NF synthesis algorithm runs in polynomial time—O(n²) where n is the size of the schema and FD set. This makes it practical for real-world database design, even for large schemas with many dependencies.
Let's apply the complete algorithm to a realistic example.
Problem:
Relation R(A, B, C, D, E, F, G)
Functional Dependencies F = { A → B, A → C, C → D, CD → E, E → F, F → G }
Verification:
✓ All relations in 3NF: Each relation has the FD determinant as its key, so all non-trivial FDs are on superkeys
✓ Lossless join: R1 contains candidate key {A} of original R
✓ Dependency preserving: All FDs from Fc appear in exactly one relation:
We've thoroughly explored the 3NF synthesis algorithm—the systematic procedure for achieving Third Normal Form with guaranteed properties. Let's consolidate the key insights:
What's Next:
Now that you understand the algorithm, the final page presents comprehensive 3NF examples from various domains, showing how the synthesis algorithm produces practical, real-world database schemas. You'll see the algorithm applied to e-commerce, healthcare, education, and other domains.
You now have complete mastery of the 3NF synthesis algorithm. You can decompose any relation into 3NF while guaranteeing lossless join and dependency preservation—the theoretical foundation for practical database normalization.