Exercises — SQL DDL — CREATE, ALTER, DROP, TRUNCATE
This page is a self-testing ladder. Each rung is harder than the last. Try the problem yourself first, then open the collapsible solution. Parent topic: SQL DDL — CREATE, ALTER, DROP, TRUNCATE.
Keep this one picture in mind the whole way down — it names the four verbs and what each one touches.

Level 1 — Recognition
Exercise 1.1
Which of the four DDL verbs — CREATE, ALTER, DROP, TRUNCATE — removes all rows but keeps the table's columns and constraints?
Recall Solution 1.1
==TRUNCATE==.
Why: TRUNCATE TABLE t deallocates the data pages so every row vanishes, but the shell (the column list, types, and constraints — the "blueprint") is untouched. DROP would delete the shell too; DELETE also keeps the shell but it is DML, not a DDL verb, and it is slower.
Exercise 1.2
True or false: ALTER TABLE students DROP COLUMN phone; deletes the entire students table.
Recall Solution 1.2
False.
The keyword DROP appears, but it is glued to COLUMN phone. It removes only that one column. The table and every other column survive. Only a bare DROP TABLE students; deletes the whole object.
Exercise 1.3
For each statement, name the single DDL verb it uses:
CREATE TABLE orders (...);ALTER TABLE orders ADD paid BOOLEAN;TRUNCATE TABLE orders;DROP TABLE IF EXISTS orders;
Recall Solution 1.3
CREATE— builds a new object.ALTER— edits an existing object's definition.TRUNCATE— empties all rows, keeps structure.DROP— deletes the whole object (IF EXISTSjust stops an error if it is already gone).
Level 2 — Application
Exercise 2.1
Write a CREATE TABLE for books with: an integer id that is the primary key; a title text field of at most 200 characters that must be present; a pages integer that must be greater than 0; and an isbn that must be unique.
Recall Solution 2.1
CREATE TABLE books (
id INT PRIMARY KEY, -- unique, not-null handle
title VARCHAR(200) NOT NULL, -- must be present
pages INT CHECK (pages > 0), -- domain rule
isbn VARCHAR(20) UNIQUE -- no duplicates
);Why each piece: PRIMARY KEY = UNIQUE + NOT NULL gives every row a guaranteed handle. NOT NULL on title forbids a nameless book. CHECK (pages > 0) rejects zero or negative page counts at the database level, so even a buggy app can't insert them. UNIQUE on isbn stops two books claiming the same ISBN. See Constraints — PRIMARY KEY, FOREIGN KEY, CHECK, UNIQUE.
Exercise 2.2
The books table already has thousands of rows. Add a new column language (text, max 10 chars) that must never be NULL. Write the statement so it does not fail.
Recall Solution 2.2
ALTER TABLE books ADD language VARCHAR(10) NOT NULL DEFAULT 'en';Why the DEFAULT: the moment you add a NOT NULL column, every existing row needs a value. With no default, those rows would instantly violate NOT NULL and the whole ALTER is rejected. The DEFAULT 'en' back-fills every existing row, so the rule is satisfied and the statement succeeds.
Exercise 2.3
You want to permanently delete the books table inside a deployment script that might run twice. Write the safe, idempotent statement.
Recall Solution 2.3
DROP TABLE IF EXISTS books;Why IF EXISTS: on the first run the table is dropped; on the second run it is already gone. A plain DROP TABLE books; would then throw an error and halt the script. IF EXISTS makes the command idempotent — running it again does no harm.
Level 3 — Analysis
Exercise 3.1
In MySQL/InnoDB you run, in this order:
START TRANSACTION;
TRUNCATE TABLE books;
ROLLBACK;After this, are the rows back? Explain the mechanism.
Recall Solution 3.1
No — the rows are gone permanently.
Mechanism: TRUNCATE is a DDL statement, and DDL auto-commits. An implicit COMMIT fires before TRUNCATE runs (and the truncate itself is not undoable). By the time your ROLLBACK executes, the transaction it would undo has already been committed and closed — there is nothing left to roll back. Had you used DELETE FROM books; instead, that is DML and fully transactional, so the ROLLBACK would have restored every row. See Transactions and ACID.
Exercise 3.2
departments has rows, and students.dept_id is a FOREIGN KEY referencing departments(id). You run DROP TABLE departments;. Predict the outcome and explain the two things CASCADE would change.
Recall Solution 3.2
Outcome: the DROP fails with a dependency error. A foreign key still points at departments, and the database refuses to leave the students table pointing at a table that no longer exists — that would break referential integrity.
What DROP TABLE departments CASCADE; changes:
- It forces the drop of
departmentsanyway, and - it also drops the dependent foreign-key constraint on
studentsso nothing is left dangling. Thestudentsrows survive, but they lose the FK rule. See Referential Integrity & CASCADE.
Exercise 3.3
Two teams both need to "clear a table". Team A must delete only rows where status = 'archived'; Team B must empty the whole 50-million-row table as fast as possible and doesn't care about rollback. Which command should each use, and why can't they swap?
Recall Solution 3.3
- Team A →
DELETE FROM t WHERE status = 'archived';— onlyDELETEaccepts aWHEREfilter.TRUNCATEhas noWHERE; it is all-or-nothing. - Team B →
TRUNCATE TABLE t;— it deallocates data pages wholesale instead of logging 50 million individual row removals, so it is dramatically faster. Rollback isn't needed, which is good because TRUNCATE isn't rollback-able anyway. Why they can't swap: Team A cannot use TRUNCATE because a filter is required. Team B could use DELETE but it would be slow (per-row logging) and log-heavy.
Level 4 — Synthesis
Exercise 4.1
Design, in order, the DDL to build these two related tables from scratch:
departments(id INT primary key, name text max 40, must be present and unique)students(id INT primary key, name text max 50 present, dept_id INT that must reference an existing department)
Then explain why the order of the two CREATE statements matters.
Recall Solution 4.1
CREATE TABLE departments (
id INT PRIMARY KEY,
name VARCHAR(40) NOT NULL UNIQUE
);
CREATE TABLE students (
id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
dept_id INT,
FOREIGN KEY (dept_id) REFERENCES departments(id)
);Why this order: students names departments(id) in its FOREIGN KEY. The referenced table must already exist when that constraint is created, so departments has to be built first. Reverse the order and the second CREATE fails: it references a table that doesn't yet exist. (Symmetrically, when dropping, you must drop students first, or drop departments with CASCADE.)
Exercise 4.2
Starting from the students table above, write a sequence of ALTER statements that:
- adds an
email VARCHAR(100)column that must be unique, - adds a rule that
idvalues stay below 1,000,000, - renames
nametofull_name.
Recall Solution 4.2
ALTER TABLE students ADD email VARCHAR(100) UNIQUE; -- 1
ALTER TABLE students ADD CONSTRAINT chk_id CHECK (id < 1000000); -- 2
ALTER TABLE students RENAME COLUMN name TO full_name; -- 3Why each: step 1 adds a column and attaches a UNIQUE constraint in one go — allowed because no existing email values exist to clash. Step 2 uses a named constraint (chk_id) so it can be dropped by name later. Step 3 RENAME COLUMN edits the live blueprint without touching the stored values. All three are ALTER — the table survives throughout.
Level 5 — Mastery
Exercise 5.1 (Debug)
A junior engineer runs the script below and it fails on the second run. Find every bug and rewrite the script so it is safe to run repeatedly.
DROP TABLE departments;
DROP TABLE students;
CREATE TABLE students (
id INT PRIMARY KEY,
dept_id INT,
FOREIGN KEY (dept_id) REFERENCES departments(id)
);
CREATE TABLE departments (
id INT PRIMARY KEY,
name VARCHAR(40) NOT NULL
);Recall Solution 5.1
Bugs:
- Drop order is wrong / unsafe.
departmentsis dropped first, butstudentsstill has a foreign key on it → dependency error. Drop the child (students) first. - No
IF EXISTS. On a fresh database (or the second run pattern) a bareDROP TABLEon an absent table errors and halts the script — it is not idempotent. - Create order is wrong.
studentsis created beforedepartments, but itsFOREIGN KEYreferencesdepartments(id)→ the referenced table doesn't exist yet → error. Create the parent first.
Fixed, idempotent script:
DROP TABLE IF EXISTS students; -- child first
DROP TABLE IF EXISTS departments; -- then parent
CREATE TABLE departments ( -- parent first
id INT PRIMARY KEY,
name VARCHAR(40) NOT NULL
);
CREATE TABLE students ( -- then child
id INT PRIMARY KEY,
dept_id INT,
FOREIGN KEY (dept_id) REFERENCES departments(id)
);Rule of thumb: drop children → parents; create parents → children. The dependency arrow points from child to parent, so you build in the direction of the arrow and demolish against it.
Exercise 5.2 (Design under constraint)
You must empty the departments table completely, but students.dept_id references it. TRUNCATE TABLE departments; refuses to run. Give two distinct correct approaches and state a consequence of each.
Recall Solution 5.2
Approach A — empty the child first, then the parent:
TRUNCATE TABLE students;
TRUNCATE TABLE departments;With no students rows left, no foreign-key value points at departments, so truncation is now allowed. Consequence: you also lose all students rows — acceptable only if that is intended.
Approach B — use DELETE with cascade behaviour set up on the FK:
DELETE FROM departments; -- if the FK was defined ON DELETE CASCADEIf the foreign key has ON DELETE CASCADE, deleting a department automatically deletes the students pointing to it. Consequence: it is per-row and logged (slower than TRUNCATE), but it is transactional — you can wrap it in a transaction and roll back if needed. See Referential Integrity & CASCADE and Transactions and ACID.
Recall One-line summary to lock it in
Build parents before children, demolish children before parents; TRUNCATE/DROP auto-commit so they can't be rolled back; a NOT NULL column added to populated data needs a DEFAULT; and foreign keys make the database refuse any operation that would leave a dangling reference.