By the end of this chapter, you will be able to:
Mastering these skills will help you manage databases efficiently, making sure information is accurate and useful in real-world business environments.
Compiled by: John Okoth
A business rule is a statement of how an organisation works, such as "every repair job belongs to a customer" or "a repair charge can never be negative". When the rules are stored in the database itself, as constraints, the DBMS refuses any data that breaks them, whichever program or user enters it. Rules that are checked only in an application screen can be bypassed by another program, an import file or a direct SQL statement, which is why the important ones are written into the database design.
Example: a bicycle repair shop applies these rules. Each customer has a phone number that no other customer has. A repair job must belong to an existing customer. A job charge cannot be negative. A job is Open until it is marked otherwise. Each of these rules becomes a constraint, as the table shows.
| Business rule | Constraint | Keyword in SQL |
|---|---|---|
| Every job has a job number that is different from all others | Primary key | PRIMARY KEY |
| A customer must have a name | Value required | NOT NULL |
| No two customers share a phone number | Unique constraint | UNIQUE |
| A job charge is never negative | Value check | CHECK |
| A new job is Open unless stated | Default value | DEFAULT |
| A job must belong to an existing customer | Referential integrity | FOREIGN KEY |
The examples in this chapter use one small sample database for a bicycle repair shop. The examples are written for MySQL 8.0, which reached end of life in April 2026 (MySQL 8.4 is the current long-term support release), and use standard SQL, except where the text says that a feature is specific to MySQL. Building the database is covered in the chapter Create database system, so the script is given here only so that every example can be run. Run it in an SQL editor. In MySQL Workbench 8.0 choose File > New Query Tab, paste the script and click the lightning bolt button; Oracle replaced 8.0 with a rebuilt MySQL Workbench 26 in September 2026, so menu names in the newer version may differ.
CREATE DATABASE repair_shop;
USE repair_shop;
CREATE TABLE customer (
customer_id INT AUTO_INCREMENT PRIMARY KEY,
full_name VARCHAR(60) NOT NULL,
phone VARCHAR(15) NOT NULL,
town VARCHAR(30),
CONSTRAINT uq_customer_phone UNIQUE (phone)
);
CREATE TABLE part (
part_code VARCHAR(10) PRIMARY KEY,
part_name VARCHAR(40) NOT NULL,
unit_price DECIMAL(8,2) NOT NULL CHECK (unit_price >= 0),
stock_qty INT NOT NULL DEFAULT 0
);
CREATE TABLE repair_job (
job_id INT AUTO_INCREMENT PRIMARY KEY,
customer_id INT NOT NULL,
job_date DATE NOT NULL,
description VARCHAR(100) NOT NULL,
charge DECIMAL(8,2) NOT NULL CHECK (charge >= 0),
status VARCHAR(10) NOT NULL DEFAULT 'Open',
CONSTRAINT fk_job_customer FOREIGN KEY (customer_id) REFERENCES customer (customer_id)
);
CREATE TABLE job_part (
job_part_id INT AUTO_INCREMENT PRIMARY KEY,
job_id INT NOT NULL,
part_code VARCHAR(10) NOT NULL,
quantity INT NOT NULL CHECK (quantity > 0),
CONSTRAINT uq_job_part UNIQUE (job_id, part_code),
CONSTRAINT fk_jp_job FOREIGN KEY (job_id) REFERENCES repair_job (job_id),
CONSTRAINT fk_jp_part FOREIGN KEY (part_code) REFERENCES part (part_code)
);
The four tables are customer, part, repair_job and job_part, which records the parts used on each job. A CHECK constraint is enforced from MySQL 8.0.16; in earlier versions MySQL read it and ignored it.
A unique constraint states that no two rows of a table may hold the same value in a column, or the same combination of values in a group of columns. The DBMS builds an index to check each new value and refuses an INSERT or UPDATE that would create a duplicate. A primary key is also unique, but the two differ: a table has only one primary key and its columns cannot be empty, while a table may have many unique constraints.
| Feature | Primary key | Unique constraint |
|---|---|---|
| Number per table | One | Many |
| Empty values (NULL) | Not allowed | Allowed in MySQL, and several rows may hold NULL |
| Purpose | Identify each row and be the target of foreign keys | Stop duplicates in other columns that must be distinct |
| Example in the sample database | customer_id | phone in customer |
In the customer table the constraint uq_customer_phone makes sure that one phone number belongs to one customer. A second customer with the same number is refused.
INSERT INTO customer (full_name, phone, town)
VALUES ('Test Person', '0700000101', 'Nakuru');
If the number 0700000101 is already stored, MySQL answers with an error like this one and stores nothing:
ERROR 1062 (23000): Duplicate entry '0700000101' for key 'customer.uq_customer_phone'
A unique constraint can cover several columns together. The constraint uq_job_part on job_part (job_id, part_code) allows the same part on many jobs and many parts on one job, but it forbids listing the same part twice on the same job, so a second line for the same part must update the quantity instead.
A unique constraint can be added to a table that already exists, and removed when the rule no longer applies. In MySQL the constraint is dropped with DROP INDEX, because it is implemented as an index.
ALTER TABLE customer ADD CONSTRAINT uq_customer_phone UNIQUE (phone);
ALTER TABLE customer DROP INDEX uq_customer_phone;
The ADD statement fails if the table already holds duplicates, so the duplicates are searched for first.
SELECT phone, COUNT(*) AS times_used
FROM customer
GROUP BY phone
HAVING COUNT(*) > 1;
Every phone number returned by this query must be corrected or removed before the constraint can be added.
Guidelines for using unique constraints:
Referential integrity is the rule that a foreign key value must match an existing primary key value in the parent table, or be NULL where the column allows it. It stops orphan records: rows that refer to a parent that does not exist. In the sample database repair_job.customer_id refers to customer.customer_id, so every job must belong to a customer that is in the customer table.
The DBMS enforces the rule in two directions:
A job for a customer number that does not exist is refused.
INSERT INTO repair_job (customer_id, job_date, description, charge)
VALUES (99, '2026-03-10', 'Puncture repair', 200.00);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`repair_shop`.`repair_job`, CONSTRAINT `fk_job_customer` FOREIGN KEY (`customer_id`) REFERENCES `customer` (`customer_id`))
Deleting a customer who still has jobs is refused in the same way, with error 1451, because the jobs would be left without a parent:
DELETE FROM customer WHERE customer_id = 1;
The rule chosen for the parent row is set with the ON DELETE and ON UPDATE options of the foreign key.
| Option | Effect when a parent row is deleted | Use |
|---|---|---|
| RESTRICT or NO ACTION | The deletion is refused while child rows exist. This is the default | Records that must be kept, such as jobs |
| CASCADE | The child rows are deleted automatically | Rows that have no meaning without the parent, such as the parts listed on a job |
| SET NULL | The foreign key in the child rows becomes NULL, so the column must allow NULL | Optional links, such as the mechanic who handled a job |
The rule for job_part can be changed so that the part lines of a job are removed when the job is deleted:
ALTER TABLE job_part DROP FOREIGN KEY fk_jp_job;
ALTER TABLE job_part
ADD CONSTRAINT fk_jp_job FOREIGN KEY (job_id)
REFERENCES repair_job (job_id) ON DELETE CASCADE;
Referential integrity also decides the order of work. Rows are inserted parent first: the customer before the job, and the job before its parts. They are deleted child first: the parts of a job, then the job, then the customer. Foreign keys are enforced by the InnoDB storage engine, which is the default in MySQL 8.0; tables in the older MyISAM engine accept foreign key definitions but ignore them.
Create a free account to open more of this chapter.
Free: practical guides, quick cards, workplace scenarios and more.
Create a free accountType: Individual
| Tools & Equipment | Materials |
|---|---|
| Relational Database Management System (MySQL, PostgreSQL, or MS SQL Server) | Rewritable Compact Disc (CD-RW) |
| Data Modelling Tool (Draw.io, Lucidchart, or EdrawMax) |
| S/N | Item | Quantity |
|---|---|---|
| 1 | Relational Database Management System (MySQL, PostgreSQL, or MS SQL Server) | 1 instance per Candidate |
| 2 | Data Modelling Tool (Draw.io, Lucidchart, or EdrawMax) | 1 license per Candidate |
| 3 | Rewritable Compact Disc (CD-RW) | 1 Pc per Candidate |
| Items to be Evaluated | Marks Available | Marks Obtained | Comments |
|---|---|---|---|
| TASK 1: Map and Define Database Schema | |||
| Mapped entities from the ERD into six (6) relations (Award 1 mark for each correct relation mapped) | 3 | ||
| Specified attributes for the six (6) relations with appropriate data types (Award 1 mark for each relation’s attributes correctly specified) | 6 | ||
| Specified primary keys for the six (6) relations (Award 0.5 mark for each correct primary key specified) | 3 | ||
| Specified composite primary keys for the Exams and Subject-Teacher relations (Award 1 mark for each composite key correctly specified) | 2 | ||
| Enforced referential integrity by specifying foreign keys in referencing relations (Award 1 mark for each correct foreign key constraint enforced) | 4 | ||
| Printed the relational schema (Award 1 mark for clear printout of schema) | 1 | ||
| Sub-Total | 19 | ||
| TASK 2: Create and Populate Database | |||
| Created the database (Award 1 mark for successful database creation) | 1 | ||
| Created six (6) relations with required attributes and data types (Award 2 marks per relation correctly created with attributes and types) | 12 | ||
| Enforced entity integrity (primary key) constraints in the six (6) relations (Award 0.5 mark per relation enforcing primary key) | 3 | ||
| Enforced referential integrity (foreign key) constraints in the six (6) relations (Award 1 mark for each relation with foreign key constraints) | 4 | ||
| Utilized best practices in database design: normalization and consistent naming scheme (Award 1 mark each for normalization, naming consistency, and design clarity) | 3 | ||
| Inserted at least 5 records into each of the six (6) relations (Award 2 marks per relation for correct data insertion) | 12 | ||
| Sub-Total | 35 | ||
| TASK 3: Data Retrieval and Manipulation Queries | |||
| Retrieved students whose first name starts with letter 'M' using LIKE and WHERE clause (Award 1 mark each for LIKE usage, WHERE clause, and correct output) | 3 | ||
| Identified the group with the largest number of students using JOIN, COUNT, GROUP BY, ORDER BY DESC and LIMIT (Award 1 mark each for JOIN, COUNT & GROUP BY, ORDER BY DESC, LIMIT, and correct result) | 5 | ||
| Retrieved teachers who teach IT using JOIN and WHERE clause on subjectTitle (Award 1 mark each for JOIN, WHERE clause, and correct results) | 3 | ||
| Renamed subject titled 'ICT' to 'Digital Literacy' using UPDATE with SET and WHERE clauses (Award 1 mark each for UPDATE, SET and WHERE, and correct update) | 3 | ||
| Deleted teacher associated with the least performed subject using DELETE with subquery and JOIN (Award 1 mark each for DELETE query, subquery, JOIN usage, and correct deletion) | 4 | ||
| Sub-Total | 18 | ||
| TASK 4: Create and Use Database View | |||
| Created a view named performance using CREATE VIEW and AS clauses with subqueries and joins (Award 1 mark each for CREATE VIEW, AS clause, correct joins, and correct output) | 4 | ||
| Generated a report for an individual student's performance using query on the performance view with WHERE clause (Award 1 mark each for querying the view, WHERE clause, and correct output) | 3 | ||
| Sub-Total | 7 | ||
| PRODUCT CHECKLIST | |||
| Database relations correctly created with specified attributes matching ERD and data types (Award 5 marks for full schema accuracy and conformity) | 5 | ||
| Data inserted correctly into all six relations with integrity constraints enforced (Award 5 marks for complete, valid, and consistent data population) | 5 | ||
| All SQL queries produce correct and expected results as per instructions (Award 8 marks for correct and efficient query results) | 8 | ||
| Sub-Total | 18 | ||
| GRAND TOTAL | 97 | ||
Type: Individual
| Tools & Equipment | Materials |
|---|---|
| Relational Database Management System (MySQL Server 8.0) | |
| SQL Client Tool (MySQL Workbench or equivalent) | |
| Notebook and Pen |
| S/N | Item | Quantity |
|---|---|---|
| 1 | Relational Database Management System (MySQL Server 8.0) | 1 Pc per Candidate |
| 2 | SQL Client Tool (MySQL Workbench or equivalent) | 1 Pc per Candidate |
| 3 | Notebook and Pen | 1 Pc per Candidate |
| Items to be Evaluated | Marks Available | Marks Obtained | Comments |
|---|---|---|---|
| TASK 1: Insert Student Records | |||
| Candidate connects to the database using the SQL client (Award 1 mark for successful connection) | 1 | ||
| Candidate writes correct INSERT INTO statements for Students table (Award 1 mark for each correctly formatted INSERT statement up to 4) | 4 | ||
| Candidate inserts at least 10 distinct student records with valid data types (Award 1 mark for every 3 correctly inserted records) | 4 | ||
| Candidate commits the transactions or saves changes successfully (Award 1 mark for successful commit) | 1 | ||
| Sub-Total | 10 | ||
| TASK 2: Insert Enrollment Records | |||
| Candidate writes correct INSERT INTO statements for Enrollments table (Award 1 mark for each correctly formatted INSERT statement up to 4) | 4 | ||
| Candidate inserts at least 15 enrollment records linking students to courses with valid foreign keys (Award 1 mark for every 3 correctly inserted enrollment records) | 5 | ||
| Candidate ensures referential integrity is not violated during insertion (Award 1 mark if no foreign key constraint errors occur) | 1 | ||
| Candidate commits the transactions or saves changes successfully (Award 1 mark for successful commit) | 1 | ||
| Sub-Total | 11 | ||
| PRODUCT CHECKLIST | |||
| All 10 student records correctly inserted with accurate attribute values and data types (Award 1 mark for every 2 correct student records, max 5) | 5 | ||
| All 15 enrollment records correctly inserted linking existing students and courses (Award 1 mark for every 3 correct enrollment records, max 6) | 6 | ||
| Sub-Total | 11 | ||
| GRAND TOTAL | 32 | ||
At the start of this chapter we promised you would be able to:
Tick each one you can genuinely do.
So, are you there yet?
You're competent when you can confidently do 50% or more of what this chapter promised.
Sign in to record how you're doing.