Databases
Every system in this course so far has needed somewhere to keep its data, this chapter is about doing that properly: why flat files break down at scale, how a relational database organises data into linked tables, how normalisation removes redundancy by design, what a DBMS actually does for you, and how to read and write the SQL that queries and builds it all. This chapter covers Cambridge 9618 syllabus sections 8.1, 8.2 and 8.3.
This chapter covers Cambridge 9618 syllabus section 8.1, the limitations of file-based storage that databases exist to solve, the terminology of the relational model, entity-relationship diagrams, and normalisation up to Third Normal Form; section 8.2, what a Database Management System actually provides on top of raw storage; and section 8.3, the SQL you need to both read and write, covering DDL (CREATE, ALTER) and DML (SELECT, INSERT, UPDATE, DELETE, including JOIN and the aggregate functions and GROUP BY that are easy to miss in a quick read of the syllabus).
Limitations of the File-Based Approach
Before databases, data was stored in separate flat files, one per application, each with no awareness of the others. This caused problems serious enough that the relational database was invented specifically to solve them.
| Problem | Description | Example |
|---|---|---|
| Data redundancy | The same data is stored in multiple files | A customer's address stored in both the sales file and the delivery file |
| Data inconsistency | Redundant copies get out of sync with each other | The address is updated in one file but not the other |
| Data isolation | Hard to access or combine data across multiple files | Cross-referencing customer orders with inventory requires manual work |
| Data dependency | Programs are tied to a specific file structure | Changing the file format breaks every program that uses it |
| No data integrity | No validation is enforced at the storage level | A file happily stores age = -5 with no error |
| No concurrent access control | Multiple users accessing the same file at once causes corruption | Two users edit the same record simultaneously and one edit is silently lost |
Try it: watch redundancy break in a file-based system
The customer's address is edited in the sales file below. Click update and watch what happens in the delivery file, which has no idea the sales file even exists.
Key Database Terminology
These terms are used precisely and interchangeably with their everyday-spreadsheet equivalents in exam mark schemes, know both names for each.
| Term | Definition | Spreadsheet analogy |
|---|---|---|
| Entity | A real-world object or concept about which data is stored | A category, e.g. Student, Course |
| Attribute | A property or characteristic of an entity | A column heading, e.g. StudentName |
| Table / Relation | A 2D structure of rows and columns storing entity data | A spreadsheet tab |
| Record / Tuple / Row | One complete set of related data for a single entity instance | One row in a spreadsheet |
| Field / Column | A single attribute's values for all records | One column in a spreadsheet |
| Primary Key (PK) | An attribute, or set of attributes, that uniquely identifies each record in a table | A unique ID number |
| Foreign Key (FK) | An attribute in one table that references the primary key of another, creating a relationship | A link between tables |
| Composite Key | A primary key made of two or more fields combined | OrderID + ProductID together forms a unique key |
| Index | A data structure that speeds up searches on a field | A book's index, letting you find pages faster than reading cover to cover |
Sample Database: School System
These two linked tables are used as the running example for the rest of this chapter, including the interactive SQL playground later on, get familiar with their structure now.
Student
| StudentID 🔑 | FirstName | LastName | DateOfBirth | CourseID 🔗 |
|---|---|---|---|---|
| S001 | Arjun | Patel | 2007-03-12 | C01 |
| S002 | Fatima | Khan | 2006-11-08 | C02 |
| S003 | James | Smith | 2007-05-22 | C01 |
| S004 | Sara | Ahmed | 2007-01-15 | C02 |
🔑 = Primary Key | 🔗 = Foreign Key (references the Course table)
Course
| CourseID 🔑 | CourseName | TeacherID 🔗 |
|---|---|---|
| C01 | Computer Science | T03 |
| C02 | Mathematics | T07 |
Entity-Relationship Diagrams & Relationships
Entity-relationship (ER) diagrams show entities and the relationships between them, including cardinality, how many of each entity can relate to the other. There are three cardinalities to know, and they are implemented in a relational database in different ways.
Try it: explore each relationship type
| Relationship | Meaning | Example | Implementation |
|---|---|---|---|
| One-to-One (1:1) | Each A links to at most one B, and vice versa | Person ↔ Passport | Foreign key placed in either table |
| One-to-Many (1:M) | One A links to many B, but each B links to only one A | Teacher → many Courses | Foreign key placed in the "many" table |
| Many-to-Many (M:M) | One A links to many B, and one B links to many A | Students ↔ Courses | Resolved with a junction table |
StudentCourse table with StudentID + CourseID together as its primary key, and each as a foreign key referencing its own table.
Normalisation: First Normal Form (1NF)
1NF rules
- Every cell contains a single, atomic (indivisible) value
- No repeating groups of columns
- All values in a column are the same data type
- Each row is unique, and has a primary key
Student(ID, Name, Subject1, Subject2, Subject3), repeating groups of columns for what is really the same kind of data.
StudentSubject(StudentID, SubjectName), each row is one student/subject pair, with no repeating columns.
Try it: normalise a table step by step
The unnormalised table below is a real exam-style starting point. Step through 1NF, then continue into 2NF and 3NF in the next section, watching the table split at each stage.
OrderDetail(OrderID, OrderDate, ProductID, ProductName, ProductPrice, Quantity), with OrderID + ProductID repeating for each product ordered.Normalisation: 2NF and 3NF
2NF rules
- Must already be in 1NF
- No partial dependencies: every non-key attribute must depend on the whole primary key, not just part of it
- Only relevant when the primary key is composite, a single-field primary key is automatically in 2NF
OrderDetail(OrderID, ProductID, ProductName), ProductName depends only on ProductID, not on the full composite key OrderID + ProductID.
Move ProductName out into its own Product(ProductID, ProductName) table.
3NF rules
- Must already be in 2NF
- No transitive dependencies: non-key attributes must not depend on other non-key attributes
Student(StudentID, CourseID, CourseName), CourseName depends on CourseID, which is itself not the primary key, not directly on StudentID.
Separate out a Course(CourseID, CourseName) table, Student keeps only CourseID as a foreign key.
Continue the stepper from the previous section here, if you have not already reached 3NF.
Database Management Systems
A Database Management System (DBMS) is software that sits between the user (or an application) and the physical data files, handling the creation, maintenance, security and querying of a database so that no program ever has to touch the raw storage directly. This is the layer that turns a pile of files back into the single, consistent, controlled resource that Section 1 showed file-based systems could never be.
| Feature | What it does |
|---|---|
| Data dictionary | Stores metadata about the database itself, table names, field names, data types, constraints and relationships, so the DBMS always knows the structure of its own data |
| Data modelling / logical schema | Provides tools to design the logical structure of the database (entities, attributes, relationships) independently of how it is physically stored on disk |
| Data integrity | Enforces constraints automatically, primary key uniqueness, foreign key referential integrity, data type checks, so invalid data is rejected at the point of entry |
| Data security / access rights | Controls who can read, insert, update or delete data, down to individual table or field level, through usernames, passwords and permission levels |
| Concurrent access control | Manages multiple users accessing and editing the database at the same time without one user's changes overwriting another's, usually through locking |
| Developer interface | Provides an Application Programming Interface (API) so external programs can connect to, query and update the database without touching the underlying files |
| Query processor | Accepts a query written in a high-level language such as SQL, works out the most efficient way to execute it, and returns the result |
ACID Properties of Transactions
A transaction is a single logical unit of work made up of one or more database operations, for example "transfer $50 from Account A to Account B" is really two operations, a debit and a credit, that must both succeed or both fail together. A DBMS guarantees four properties for every transaction, remembered by the acronym ACID.
A transaction is treated as a single indivisible unit, either every operation in it completes, or none of them do. If the credit step fails after the debit step succeeded, the whole transaction rolls back and the debit is undone too.
A transaction can only take the database from one valid state to another valid state, all rules and constraints (primary keys, foreign keys, data types) must still hold once the transaction finishes.
Concurrent transactions must not interfere with each other, the result of running transactions at the same time must be the same as if they had run one after another in some order.
Once a transaction has been committed, it is permanent, it survives a power cut or system crash immediately afterwards, usually because it has been written to non-volatile storage.
Try it: watch atomicity protect a bank transfer
Below is a $50 transfer from Account A to Account B, modelled as two steps: debit A, then credit B. Run it normally, or simulate a crash between the two steps, and compare what happens with a DBMS enforcing atomicity versus a naive file-based system that has no concept of a transaction at all.
Data Definition Language (DDL)
SQL (Structured Query Language) is split into two families of commands: DDL, which defines and modifies the structure of a database (creating and altering databases and tables), and DML, which manipulates the data stored inside that structure (querying, inserting, updating, deleting rows). This section covers DDL.
Defines structure. CREATE, ALTER, DROP. Answers "what does the database look like?"
Manipulates data. SELECT, INSERT, UPDATE, DELETE. Answers "what data is in it?"
Creating a database and a table
CREATE DATABASE SchoolSystem;
CREATE TABLE Student (
StudentID CHARACTER(4) PRIMARY KEY,
FirstName VARCHAR(20),
LastName VARCHAR(20),
DateOfBirth DATE,
CourseID CHARACTER(3),
FOREIGN KEY (CourseID) REFERENCES Course(CourseID)
);
SQL data types
| Data type | Stores | Example |
|---|---|---|
CHARACTER(n) | Fixed-length text of exactly n characters, padded with spaces if shorter | CHARACTER(4) for "S001" |
VARCHAR(n) | Variable-length text up to n characters, no padding | VARCHAR(20) for a name |
BOOLEAN | True or false | IsActive |
INTEGER | Whole numbers | Quantity |
REAL | Numbers with a decimal point | Price |
DATE | A calendar date | 2007-03-12 |
TIME | A time of day | 14:30:00 |
Altering a table after creation
ALTER TABLE changes the structure of a table that already exists, adding or removing columns, or adding keys that were not defined at creation time.
ALTER TABLE Student ADD Email VARCHAR(40);
ALTER TABLE Student ADD PRIMARY KEY (StudentID);
ALTER TABLE Student
ADD FOREIGN KEY (CourseID) REFERENCES Course(CourseID);
Try it: build a CREATE TABLE statement
Add columns, pick a data type for each, and mark one as the primary key, the SQL below updates live as you build the table.
Querying with SELECT
Every query you write starts from SELECT. The three clauses below, in this order, cover the large majority of exam questions.
SELECT column1, column2 FROM TableName WHERE condition ORDER BY column1 ASC | DESC;
| Clause | Purpose |
|---|---|
SELECT | Which columns to return. SELECT * returns every column |
FROM | Which table to read from |
WHERE | Filters rows by a condition, only matching rows are returned |
ORDER BY | Sorts the result, ASC (default) or DESC |
WHERE conditions
WHERE CourseID = 'C01' WHERE DateOfBirth > '2006-12-31' WHERE FirstName LIKE 'A%' WHERE CourseID = 'C01' AND LastName = 'Smith' WHERE CourseID = 'C01' OR CourseID = 'C02'
| Operator | Meaning |
|---|---|
=, <>, >, <, >=, <= | Standard comparisons |
AND, OR, NOT | Combine or negate conditions |
LIKE | Pattern match, % means any number of characters |
BETWEEN a AND b | Inclusive range check |
Aggregate Functions & GROUP BY
Aggregate functions perform a calculation across many rows and return a single summary value, instead of returning the rows themselves. They are one of the most commonly missed topics in a quick read of the syllabus, but come up regularly in exam questions.
| Function | Returns |
|---|---|
COUNT(column) | The number of rows |
SUM(column) | The total of a numeric column |
AVG(column) | The average (mean) of a numeric column |
MAX(column) / MIN(column) | The largest / smallest value |
SELECT COUNT(*) FROM Student; SELECT CourseID, COUNT(*) AS NumStudents FROM Student GROUP BY CourseID;
GROUP BY collects rows that share the same value in a column into a single group, and then the aggregate function is calculated once per group rather than once for the whole table. SELECT CourseID, COUNT(*) FROM Student GROUP BY CourseID does not count all students, it counts students separately for each distinct CourseID, producing one output row per course.
Using the Student table from Section 3 (S001/S003 on C01, S002/S004 on C02), SELECT CourseID, COUNT(*) FROM Student GROUP BY CourseID groups the four rows into two groups by CourseID, then counts each group:
| CourseID | COUNT(*) |
|---|---|
| C01 | 2 |
| C02 | 2 |
SELECT list must either be inside an aggregate function, or listed in GROUP BY. SELECT FirstName, CourseID, COUNT(*) FROM Student GROUP BY CourseID is invalid, FirstName is neither aggregated nor grouped by, so SQL cannot know which one FirstName to show per group.
Run GROUP BY and aggregate queries yourself in the SQL Query Playground in the next section.
JOIN, INSERT, UPDATE, DELETE
The Student and Course tables have been kept separate throughout this chapter, on purpose, that is what normalisation demands. But most useful questions need data from both at once, that is what JOIN is for.
INNER JOIN
SELECT Student.FirstName, Student.LastName, Course.CourseName FROM Student INNER JOIN Course ON Student.CourseID = Course.CourseID;
INNER JOIN Course ON Student.CourseID = Course.CourseID matches every row in Student to the row in Course whose CourseID is equal, producing one combined row per match. This is exactly what the foreign key was for, it is the column that makes the join possible.
INSERT, UPDATE, DELETE
INSERT INTO Student (StudentID, FirstName, LastName, DateOfBirth, CourseID)
VALUES ('S005', 'Wei', 'Chen', '2007-02-18', 'C01');
UPDATE Student
SET CourseID = 'C02'
WHERE StudentID = 'S005';
DELETE FROM Student
WHERE StudentID = 'S005';
UPDATE Student SET CourseID = 'C02' with no WHERE clause updates every single row in the table, not just one. The same is true of DELETE FROM Student with no WHERE, it deletes every row. This is one of the most common serious mistakes in real SQL use, always double check the WHERE clause before running an UPDATE or DELETE.
Try it: SQL Query Playground
Pick a preset query below and run it against the live Student and Course tables. INSERT, UPDATE and DELETE actually change the displayed data, use Reset to restore the original tables.
Practice Questions
Any two of: data redundancy, the same data duplicated in multiple files; data inconsistency, duplicated copies falling out of sync with each other; data isolation, difficulty combining data held in separate files; data dependency, programs tied to a fixed file structure; no enforced data integrity; and no concurrent access control.
OrderDetail(OrderID, ProductID, ProductName, ProductPrice) has a composite primary key of OrderID + ProductID. Which normal form does this violate, and why?It violates Second Normal Form (2NF). ProductName and ProductPrice depend only on ProductID, not on the whole composite key OrderID + ProductID, so this is a partial dependency, non-key attributes must depend on the entire primary key.
A foreign key field can only store a single value referencing a single row. In a many-to-many relationship, one record would need to reference several records in the other table simultaneously, which a single field cannot hold without breaking the relational model. A junction table with a composite primary key, holding one row per valid pairing, resolves this instead.
Atomicity has been violated, the transaction was not treated as a single indivisible unit. A DBMS enforcing atomicity should roll the whole transaction back, restoring Account A's original balance, so that either both steps complete or neither does.
SELECT CourseID, COUNT(*) FROM Student GROUP BY CourseID;, this groups the rows by CourseID and counts the rows in each group separately.
DDL (Data Definition Language) defines and modifies the structure of a database, for example CREATE TABLE. DML (Data Manipulation Language) manipulates the data stored inside that structure, for example SELECT or INSERT INTO.
Concurrent access control. It is typically implemented through record locking, when one user begins editing a record, the DBMS locks it so other users cannot edit that same record until the lock is released.
