Databases · Week 2 practice: normalisation

Anomalies, functional and transitive dependencies, 1NF → 2NF → 3NF

Practice for the normalisation half of Week 2: why we normalise, the three anomalies, functional and transitive dependencies, and 1NF → 2NF → 3NF, which is the scope the slides set (“This module looks at 1NF, 2NF, 3NF”). One question is tagged beyond slides. A single music-school table is reused through the page (Q3, Q7, Q8, Q15, Q16) so you see one example go the whole way.

Multiple-choice questions check themselves when you click; for written ones, answer on paper first.

Convention check. Your slides define the normal forms in their own words, which are a little different from textbooks:
  • 1NF (slide 14) has four criteria, including “there must be a primary key”. Codd's original 1NF is only about atomic values. In a test, give the slide's four.
  • The slides' worked 1NF example adds a primary key but keeps Class 1 … Class 4 as columns; the hackr.io diagram on the same slides says 1NF “eliminates repeating groups”. Most textbooks would remove those columns at 1NF. The answers here do that and say so.
  • 2NF and 3NF are stated relative to “the primary key”. Textbooks state them relative to every candidate key. Same answer for every example here.

A. What normalisation is for

Q1multiple choicewhat is normalisation

According to the lecture, when and how is normalisation done?

Explanation

Answer: Normalisation is a process used in data modelling/database creation where you organise data and tables so they can be added to and updated efficiently. It is done manually at design time (“no click a button and do it!”). In the Week 1 design steps it is schema refinement. It was introduced by Codd alongside the relational model in the early 1970s.

Q2why normalise5 marks

Give five reasons from the lecture for normalising a database.

Show answer
  • Make the database more efficient.
  • Prevent duplicates: the same data stored in more than one place.
  • Ensure consistency: stop updates being applied to some copies but not others.
  • Prevent data not being deleted when it should be, or lost when it shouldn't be.
  • Ensure data accuracy.
  • Reduce storage space.
  • Optimise query execution times.

Without it, the database is likely to be slow and hard to manage, update and keep accurate. Notice these are Week 1's redundancy problems again: normalisation is the systematic way to apply Guideline 2 (“do not repeat information”).

Q3anomalies6 marks

A music school stores everything in one table:

Pupil NameFees PaidDate of BirthInstrumentLesson 1Lesson 2Tutor
Emma Clarke30012-Mar-08PianoTheory 1Aural 1Mr Hale
Raj Patel45001-Jul-09ViolinTheory 1OrchestraMs Osei
Lucy Moore45023-Nov-08CelloOrchestraMs Osei

Business rules: each instrument is taught by exactly one tutor (a tutor may teach several instruments); each pupil learns one instrument; pupils attend any number of group lessons.

Give one concrete INSERT, UPDATE and DELETE anomaly, in the lecture's terms.

Show answer
  • INSERT anomaly (you can't add something without adding unrelated data, or you add incomplete data): a new group lesson “Jazz Ensemble” can't be recorded until a pupil takes it, because lessons only exist as cells in pupil rows. A new pupil whose instrument isn't decided yet gets incomplete data (NULL Instrument and Tutor).
  • UPDATE anomaly (you update a record but fail to make all the necessary changes): rename “Theory 1” to “Music Theory 1”. It appears in several rows and in different columns (Lesson 1 here, Lesson 2 elsewhere). Miss one and the data is inconsistent. Same if Ms Osei's name changes.
  • DELETE anomaly (deleting one thing removes other data you wanted to keep): if Lucy Moore leaves and her row is deleted, the only record that Cello is taught by Ms Osei disappears. If Emma leaves, “Aural 1” vanishes entirely.
Q4multiple choiceanomalies

“Susan Johnson drops out; deleting her record removes all traces of Biology 2 and Biology 3.” Which anomaly is this?

Explanation

Answer: a DELETE anomaly: deleting one thing (a student) removes other data you wanted to keep (that those classes exist). This is the slides' own example.

B. Normal forms, 1NF and functional dependencies

Q5multiple choicenormal forms

The “Normalisation Levels” slide draws 1NF ⊃ 2NF ⊃ 3NF ⊃ BCNF as nested shapes. Which statement follows?

Explanation

Answer: Each normal form's definition starts “fulfils the requirements of the previous one”, so the sets nest: every 3NF table is in 2NF and 1NF, but not the other way round. The innermost (BCNF) is the strictest. The lecture notes add 4NF, 5NF, even 6NF, but 3NF is the one you'll most commonly see in practice.

Q6normal forms5 marks

According to the hackr.io diagram in the slides, what does each normal form eliminate? 1NF, 2NF, 3NF, 4NF, 5NF.

Show answer
FormEliminates
1NFrepeating groups
2NFpartial functional dependency
3NFtransitive dependency
4NFmulti-valued dependency
5NFjoin dependency

The diagram also shows each step decomposing the relation into more, smaller relations (R → R₁₁, R₁₂ → R₂₁, R₂₂, R₂₃ …). Only 1NF–3NF are in scope here; 4NF/5NF are recognition only.

Q71NF6 marks

(a) State the lecture's four criteria for 1NF. (b) Which does the music-school table break, and how?

Pupil NameFees PaidDate of BirthInstrumentLesson 1Lesson 2Tutor
Emma Clarke30012-Mar-08PianoTheory 1Aural 1Mr Hale
Raj Patel45001-Jul-09ViolinTheory 1OrchestraMs Osei
Lucy Moore45023-Nov-08CelloOrchestraMs Osei

Business rules: each instrument is taught by exactly one tutor (a tutor may teach several instruments); each pupil learns one instrument; pupils attend any number of group lessons.

Show answer

(a) (1) A single cell must not hold more than one value (atomicity). (2) There must be a primary key for identification. (3) No duplicated rows or columns. (4) Each column must have only one value for each row.

(b)

  • No primary key. Pupil Name isn't unique (two pupils could share a name), and neither is any other column. As in the slides, introduce a PupilID.
  • Repeating group / duplicated columns: Lesson 1, Lesson 2 are the same kind of column repeated. How many do you allow? Lucy has an empty one; a pupil with three lessons doesn't fit at all. (Cells are each atomic here, but the slide's own Class columns are written as “Biology 1 (Science)”, two facts in one cell: a lesson and its department. That would break atomicity.)
Q8multiple choicefunctional dependency

In the functional dependency X → Y, what does the lecture call X?

Explanation

Answer: the determinant. Y is the dependent. A functional dependency says one attribute (set) determines the value of another: whenever two rows agree on X, they must agree on Y. Read StudentID → StudentName as “StudentID determines StudentName”: know the ID and there's exactly one name.

Q9functional dependency6 marks

For the music school, decide which of these are functional dependencies. For each that is, name the determinant and dependent.

  1. PupilID → Pupil Name
  2. Pupil Name → PupilID
  3. Instrument → Tutor
  4. Tutor → Instrument
  5. PupilID → Lesson
  6. PupilID → Instrument
Show answer
  1. Yes. Determinant PupilID, dependent Pupil Name: one ID, one name.
  2. No. Two pupils can share a name, so a name can map to several IDs.
  3. Yes (business rule: each instrument has one tutor). Determinant Instrument, dependent Tutor.
  4. No. Ms Osei teaches Violin and Cello.
  5. No. A pupil attends several lessons. This is why lessons can't stay as a column of the pupil table: it's a many-to-many relationship, not a dependency.
  6. Yes (each pupil learns one instrument).

Key habit: FDs come from the business rules, not from spotting patterns in today's rows. Three rows of sample data can't prove a rule holds.

C. 2NF and 3NF

Q10multiple choice2NF

When can a partial dependency exist?

Explanation

Answer: A partial dependency is a non-key attribute depending on only part of the primary key. If the key is a single column, it has no “part” to depend on, so (slide 19) a table in 1NF with a single-column PK is already in 2NF.

Q112NF8 marks

OrderLine(order_id, product_id, quantity, order_date, customer_name, product_name, unit_price) with primary key (order_id, product_id). Rules: an order is placed on one date by one customer; each product has one name and one price.

(a) Write down the FDs. (b) Which are partial dependencies? (c) Decompose to 2NF, marking PKs and FKs.

Show answer

(a)

order_id, product_id → quantity
order_id             → order_date, customer_name
product_id           → product_name, unit_price

(b) The last two: their determinants are each part of the composite key. Only quantity depends on the entire key (how many of this product on this order).

(c) Move each partial dependency into its own table, keyed on the part of the key it depends on:

Order    (order_id, order_date, customer_name)
Product  (product_id, product_name, unit_price)
OrderLine(order_id FK → Order, product_id FK → Product, quantity)

OrderLine is now a junction table for the M:M between Order and Product (Week 1's pattern). Changing a price now means updating one row.

Q123NF7 marks

(a) Define a transitive dependency and quote Bill Kent's phrase for 3NF.
(b) Employee(emp_id, name, dept_id, dept_name, dept_floor), PK emp_id. Each employee is in one department; each department has one name and one floor. Is it in 2NF? 3NF? Decompose if needed.

Show answer

(a) A transitive dependency is when A → B and B → C, so A → C holds “through” B, where B is a non-key attribute. You can find a non-key attribute using another non-key attribute. 3NF: in 2NF and no transitive dependencies; every non-key attribute must provide “a fact about the key, the whole key, and nothing but the key”.

(b) 2NF: yes, the PK is a single column so there can be no partial dependency. 3NF: no: emp_id → dept_id → dept_name, dept_floor. Department facts depend on dept_id, a non-key attribute.

Department(dept_id, dept_name, dept_floor)
Employee  (emp_id, name, dept_id FK → Department)

The pattern is the slides' Student/Postcode split: the attribute in the middle (dept_id) becomes the PK of a new table and stays behind as a FK.

Q133NFthink4 marks

Slide 29 says “Student ID → City and City → Postcode, eventually resulting in Student ID → Postcode”. The 3NF solution on slide 30 creates (Postcode PK, City) and keeps Postcode as a FK in Student. Is the slide's FD direction consistent with its own solution? Which direction is right in the real world?

Show answer

It isn't consistent. A table (Postcode PK, City) stores the dependency Postcode → City: the key determines the other column. And in reality a postcode lies in one city, while a city has many postcodes, so City → Postcode is false. The correct chain is:

StudentID → Postcode → City        so  StudentID → City (transitively)

The slide's prose (“we can identify the City using Postcode”) agrees with this; only the arrow line is reversed. In the test, write it as StudentID → Postcode → City. If you rely on the slide's arrows, the “middle” attribute would be City, and the decomposition would come out differently. That's why getting the direction right matters. (I'd treat this as a typo on the slide; worth checking with the lecturer if you can.)

Q14identify the normal form8 marks

Give the highest of 1NF, 2NF, 3NF for each (assume each already has atomic values and a primary key, underlined), and justify:

  1. Booking(room_id, date, booked_by, room_capacity); room_id → room_capacity
  2. Student(student_id, name, postcode, city); postcode → city
  3. Room(room_id, room_name, room_capacity, room_zoom); no other dependencies
  4. Enrolment(student_id, module_id, grade, module_title); module_id → module_title
Show answer
HighestWhy
(a)1NFroom_capacity depends on only part of the composite key (room_id): partial dependency.
(b)2NFSingle-column key ⇒ 2NF, but student_id → postcode → city is transitive.
(c)3NFEvery attribute is a fact about room_id and nothing else. (This is the lecture's Room table.)
(d)1NFmodule_title depends on part of the key (module_id). grade is fine: it needs both.

Method: first check for partial dependencies (only possible with composite keys), then for non-key → non-key dependencies.

D. Putting it together

Q15full worked example12 marks

Normalise the music-school table step by step: UNF → 1NF → 2NF → 3NF. At each step, give the tables with PKs (and FKs) and say what was removed.

Pupil NameFees PaidDate of BirthInstrumentLesson 1Lesson 2Tutor
Emma Clarke30012-Mar-08PianoTheory 1Aural 1Mr Hale
Raj Patel45001-Jul-09ViolinTheory 1OrchestraMs Osei
Lucy Moore45023-Nov-08CelloOrchestraMs Osei

Business rules: each instrument is taught by exactly one tutor (a tutor may teach several instruments); each pupil learns one instrument; pupils attend any number of group lessons.

Show answer

1NF. Introduce a primary key PupilID (names aren't unique). Remove the repeating group Lesson 1/Lesson 2 by giving each pupil–lesson pair its own row:

PupilLessons(PupilID, Lesson, PupilName, FeesPaid, DOB, Instrument, Tutor)

The key is now (PupilID, Lesson), since a pupil appears once per lesson. (The slides' own example keeps Class 1–4 at 1NF and removes them at 2NF. Either way you end up in the same place.)

2NF. Partial dependencies on that composite key: PupilID → PupilName, FeesPaid, DOB, Instrument, Tutor. Nothing depends on the whole key; lessons themselves become their own table so a lesson can exist with no pupils (fixing the insert anomaly):

Pupil      (PupilID, PupilName, FeesPaid, DOB, Instrument, Tutor)
Lesson     (LessonID, LessonName)
PupilLesson(PupilID FK, LessonID FK)          -- M:M junction table

3NF. In Pupil, PupilID → Instrument → Tutor is transitive (Tutor is a fact about the instrument, not the pupil). Split it out, and give tutors their own table so a tutor's name is stored once:

Tutor      (TutorID, TutorName)
Instrument (InstrumentID, InstrumentName, TutorID FK → Tutor)
Pupil      (PupilID, PupilName, FeesPaid, DOB, InstrumentID FK → Instrument)
Lesson     (LessonID, LessonName)
PupilLesson(PupilID FK → Pupil, LessonID FK → Lesson)

Check the anomalies from Q3: a new lesson is just a row in Lesson; renaming “Theory 1” changes one row; deleting Lucy leaves “Cello → Ms Osei” intact. (Slide 21 says “program name is not dependent on the student”. Strictly, StudentID → Program does hold, as each student has one program, which is exactly why the slides keep Program ID in Student as a FK. What gets split out are the facts about the program, just as Instrument's tutor is here.)

Q16SQL3NF6 marks

Write CREATE TABLE statements for your 3NF result (use the lecture's style: integer/text/date, NOT NULL, PRIMARY KEY (…), plus REFERENCES for FKs), insert the three pupils, and write a query that rebuilds “one row per pupil per lesson, with instrument and tutor”. Run it in pgAdmin.

Show answer
Answer (run on PostgreSQL 16)
DROP TABLE IF EXISTS pupil_lesson, lesson, pupil, instrument, tutor CASCADE;

CREATE TABLE tutor (
    tutor_id integer NOT NULL,
    name     text    NOT NULL,
    PRIMARY KEY (tutor_id)
);
CREATE TABLE instrument (
    instrument_id integer NOT NULL,
    name          text    NOT NULL,
    tutor_id      integer REFERENCES tutor(tutor_id),
    PRIMARY KEY (instrument_id)
);
CREATE TABLE pupil (
    pupil_id      integer NOT NULL,
    name          text    NOT NULL,
    fees_paid     integer,
    date_of_birth date,
    instrument_id integer REFERENCES instrument(instrument_id),
    PRIMARY KEY (pupil_id)
);
CREATE TABLE lesson (
    lesson_id integer NOT NULL,
    name      text    NOT NULL,
    PRIMARY KEY (lesson_id)
);
CREATE TABLE pupil_lesson (
    pupil_id  integer REFERENCES pupil(pupil_id),
    lesson_id integer REFERENCES lesson(lesson_id),
    PRIMARY KEY (pupil_id, lesson_id)
);

INSERT INTO tutor VALUES (1, 'Mr Hale'), (2, 'Ms Osei');
INSERT INTO instrument VALUES (1, 'Piano', 1), (2, 'Violin', 2), (3, 'Cello', 2);
INSERT INTO pupil VALUES
    (101, 'Emma Clarke', 300, '2008-03-12', 1),
    (102, 'Raj Patel',   450, '2009-07-01', 2),
    (103, 'Lucy Moore',  450, '2008-11-23', 3);
INSERT INTO lesson VALUES (1, 'Theory 1'), (2, 'Aural 1'), (3, 'Orchestra');
INSERT INTO pupil_lesson VALUES (101, 1), (101, 2), (102, 1), (102, 3), (103, 3);

-- Rebuild the original "one row per pupil per lesson" view of the data
SELECT p.name AS pupil, i.name AS instrument, t.name AS tutor, l.name AS lesson
FROM pupil p
JOIN instrument   i  ON i.instrument_id = p.instrument_id
JOIN tutor        t  ON t.tutor_id      = i.tutor_id
JOIN pupil_lesson pl ON pl.pupil_id     = p.pupil_id
JOIN lesson       l  ON l.lesson_id     = pl.lesson_id
ORDER BY p.pupil_id, l.lesson_id;
Expected output
    pupil    | instrument |  tutor  |  lesson
-------------+------------+---------+-----------
 Emma Clarke | Piano      | Mr Hale | Theory 1
 Emma Clarke | Piano      | Mr Hale | Aural 1
 Raj Patel   | Violin     | Ms Osei | Theory 1
 Raj Patel   | Violin     | Ms Osei | Orchestra
 Lucy Moore  | Cello      | Ms Osei | Orchestra
(5 rows)

Table order matters: a table must exist before another can REFERENCES it, so tutor → instrument → pupil, and the drops go in reverse. JOIN … ON combines rows where the FK equals the PK (joins are on the SQL page). This is the “how do we connect all the data?” question from slide 22: the decomposition is only useful because FKs let you join the pieces back without spurious tuples, Week 1's Guideline 4.

Q17multiple choiceforeign keys

After the 2NF split into Student, Class, Program and Teacher tables, the slides ask “how do we connect all the data?”. The answer?

Explanation

Answer: foreign keys (slide 23): e.g. Program ID in Student, Teacher ID in Program, and the (Student ID, Class ID) link table. A FK also enforces referential integrity: you can't point at a program that doesn't exist.

Q18many-to-many4 marks

Slide 24 asks how teachers relate to classes: does a teacher have many classes, and does a class have many teachers? With answers “yes” and “possibly yes”, what relationship is it, and how is it stored? Why can't you just add a Teacher ID column to Class?

Show answer

Many-to-many. A Teacher ID column in Class can hold only one teacher per class (one value per cell is 1NF), so a co-taught class wouldn't fit. Use a junction table:

ClassTeacher(ClassID FK → Class, TeacherID FK → Teacher)

Exactly Week 1's rule: M:M needs an associative/junction table; 1:M puts the FK on the many side. If the school's rule were “one teacher per class”, Class.TeacherID would be correct. The business rule decides.

Q19BCNFbeyond slides2 marks

Beyond slides. The nesting diagram puts BCNF inside 3NF. In one or two sentences, what extra condition does BCNF add?

Show answer

BCNF (Boyce–Codd Normal Form) requires that every determinant is a candidate key, with no exceptions. 3NF allows one exception: a dependency X → A where A is itself part of a key. Example: Tutoring(student, module, tutor) with tutor → module and {student, module} → tutor is in 3NF but not BCNF, because tutor is a determinant but not a key. The slides say this module only examines up to 3NF, so treat this as background.