The Story — Build the House, Then Furnish It
SQL works the same way. DDL (Data Definition Language) builds the structure: it creates, alters, and drops tables. DML (Data Manipulation Language) is the moving company: it inserts, updates, and deletes the rows inside. And constraints are the building codes — rules like "every apartment needs a unique number" or "the rent must be positive" that keep bad data out.
DDL changes the structure (the table itself); DML changes the data (the rows). DDL commands auto-commit and usually can't be rolled back, so always double-check a DROP or TRUNCATE.
The SQL Command Families
Every SQL statement belongs to a family. This tutorial focuses on the two you use most — DDL and DML — but it helps to see the whole map.
Modern SQL classifies SELECT as DQL (Data Query Language), though older texts group it with DML.
| Family | Purpose | Commands |
|---|---|---|
| DDL | Define / change structure | CREATE, ALTER, DROP, TRUNCATE |
| DML | Manipulate data | INSERT, UPDATE, DELETE |
| DQL | Query data | SELECT |
| DCL | Control access | GRANT, REVOKE |
| TCL | Manage transactions | COMMIT, ROLLBACK, SAVEPOINT |
CREATE TABLE — Building the Structure
CREATE TABLE defines a new table: its name, its columns, each column's data type, and the constraints that guard it. This is always the first command when setting up a schema.
CREATE makes an empty, well-defined table — the rows come later, via INSERT.
-- Build two related tables for our company database
CREATE TABLE DEPARTMENT (
Dept_ID INT PRIMARY KEY,
Dname VARCHAR(40) NOT NULL
);
CREATE TABLE EMPLOYEE (
Emp_ID INT PRIMARY KEY,
Name VARCHAR(50) NOT NULL,
Age INT CHECK (Age >= 18),
Salary INT DEFAULT 30000,
Email VARCHAR(80) UNIQUE,
Dept_ID INT,
FOREIGN KEY (Dept_ID) REFERENCES DEPARTMENT(Dept_ID)
);
Constraints — The Guardrails of Your Data
Constraints are rules attached to columns that the database enforces automatically. Any insert or update that breaks a rule is rejected, keeping the data clean and consistent.
The database rejects the row because Age 15 violates the CHECK and the email duplicates an existing UNIQUE value.
| Constraint | What it enforces | Example |
|---|---|---|
| NOT NULL | Column can never be empty | Name VARCHAR(50) NOT NULL |
| UNIQUE | No duplicate values (one NULL allowed) | Email VARCHAR(80) UNIQUE |
| PRIMARY KEY | UNIQUE + NOT NULL; identifies each row | Emp_ID INT PRIMARY KEY |
| FOREIGN KEY | Value must exist in another table's PK | Dept_ID REFERENCES DEPARTMENT(Dept_ID) |
| CHECK | Value must satisfy a condition | CHECK (Age >= 18) |
| DEFAULT | Value used when none is given | Salary INT DEFAULT 30000 |
| AUTO_INCREMENT | Auto-generate sequential numbers | Emp_ID INT AUTO_INCREMENT |
A table has exactly one PRIMARY KEY (which forbids NULLs), but it can have many UNIQUE columns, and a UNIQUE column may hold a single NULL. Use the primary key for the main identifier, UNIQUE for other no-duplicate fields like Email.
ALTER TABLE — Changing the Structure
ALTER TABLE modifies an existing table without losing the data already in it. You can add or drop columns, change a column's type, or add and remove constraints.
Existing rows get NULL (or the DEFAULT) in the new column — no data is lost.
-- Add a column
ALTER TABLE EMPLOYEE ADD Joining_Date DATE;
-- Change a column's data type
ALTER TABLE EMPLOYEE MODIFY Name VARCHAR(80);
-- Add a constraint to an existing table
ALTER TABLE EMPLOYEE ADD CONSTRAINT chk_sal CHECK (Salary > 0);
-- Remove a column
ALTER TABLE EMPLOYEE DROP COLUMN Joining_Date;
DROP vs TRUNCATE vs DELETE — A Crucial Comparison
These three commands all "remove" something, but they are very different — and confusing them is the single most common SQL exam mistake.
DELETE removes chosen rows, TRUNCATE empties the table, DROP destroys the table itself.
| Feature | DELETE | TRUNCATE | DROP |
|---|---|---|---|
| Family | DML | DDL | DDL |
| Removes | Chosen rows | All rows | Whole table |
| WHERE clause | Yes | No | No |
| Can roll back | Yes | Usually no | No |
| Structure after | Remains | Remains | Gone |
| Speed | Slower (row by row) | Fast | Fast |
DELETE FROM EMPLOYEE WHERE Age < 21; -- removes matching rows only
TRUNCATE TABLE EMPLOYEE; -- empties the table, keeps structure
DROP TABLE EMPLOYEE; -- deletes the table completely
INSERT — Adding Rows
INSERT adds new rows. You can list all values in column order, name specific columns, or insert several rows at once. Columns you skip take their DEFAULT (or NULL).
The inserted row must satisfy every constraint, or the database rejects it.
-- Departments first (parent table, for the foreign key)
INSERT INTO DEPARTMENT VALUES (10, 'Sales'), (20, 'Tech');
-- Full row, values in column order
INSERT INTO EMPLOYEE VALUES (1, 'Raj', 30, 50000, 'raj@co.com', 10);
-- Named columns; Salary defaults to 30000, Email becomes NULL
INSERT INTO EMPLOYEE (Emp_ID, Name, Age, Dept_ID) VALUES (3, 'Amit', 19, 10);
-- Multiple rows at once
INSERT INTO EMPLOYEE VALUES
(2, 'Sara', 25, 40000, 'sara@co.com', 20);
| EMPLOYEE after the inserts | |||||
|---|---|---|---|---|---|
| Emp_ID | Name | Age | Salary | Dept_ID | |
| 1 | Raj | 30 | 50000 | raj@co.com | 10 |
| 2 | Sara | 25 | 40000 | sara@co.com | 20 |
| 3 | Amit | 19 | 30000 | NULL | 10 |
UPDATE — Changing Existing Rows
UPDATE modifies values in rows that match a WHERE condition. The WHERE clause is critical: omit it and every row is changed.
Only rows matching the WHERE condition are touched; the rest stay exactly as they were.
-- Give everyone in department 10 a 10% raise
UPDATE EMPLOYEE SET Salary = Salary * 1.10 WHERE Dept_ID = 10;
| After the UPDATE (Dept 10 rows changed) | ||
|---|---|---|
| Name | Dept_ID | Salary |
| Raj | 10 | 55000 |
| Sara | 20 | 40000 |
| Amit | 10 | 33000 |
UPDATE EMPLOYEE SET Salary = 0; with no WHERE zeroes out every salary in the table. Always write (and double-check) the WHERE clause before running an UPDATE or DELETE.
DELETE — Removing Rows
DELETE removes rows that match a condition. Unlike TRUNCATE, it is a DML command: it works row by row, supports a WHERE clause, and can be rolled back inside a transaction.
Amit (age 19) matches Age < 21 and is deleted; the table structure is untouched.
-- Remove employees younger than 21
DELETE FROM EMPLOYEE WHERE Age < 21;
-- Remove everyone (rows only) -- structure stays, but prefer TRUNCATE for speed
DELETE FROM EMPLOYEE;
| EMPLOYEE after DELETE WHERE Age < 21 | |
|---|---|
| Name | Age |
| Raj | 30 |
| Sara | 25 |
Practice Problems — Solve Them Yourself First
Here is a full mini-scenario. Try each problem before revealing the logic in the solution. We build a small college database from scratch.
Problem 1 — Create the tables
Create a COURSE table (Course_ID primary key, Title not null) and a STUDENT table with Roll (PK), Name (not null), Marks (must be 0–100), a Grade defaulting to 'NA', and Course_ID as a foreign key to COURSE.
-- Solution 1
CREATE TABLE COURSE (
Course_ID INT PRIMARY KEY,
Title VARCHAR(50) NOT NULL
);
CREATE TABLE STUDENT (
Roll INT PRIMARY KEY,
Name VARCHAR(50) NOT NULL,
Marks INT CHECK (Marks >= 0 AND Marks <= 100),
Grade CHAR(2) DEFAULT 'NA',
Course_ID INT,
FOREIGN KEY (Course_ID) REFERENCES COURSE(Course_ID)
);
Problem 2 — Insert data
Add course 101 "DBMS", then add three students. Leave one student's Grade unset to test the DEFAULT.
-- Solution 2
INSERT INTO COURSE VALUES (101, 'DBMS');
INSERT INTO STUDENT VALUES (1, 'Raj', 82, 'A', 101);
INSERT INTO STUDENT VALUES (2, 'Sara', 55, 'C', 101);
INSERT INTO STUDENT (Roll, Name, Marks, Course_ID) VALUES (3, 'Amit', 91, 101);
| Roll | Name | Marks | Grade | Course_ID |
|---|---|---|---|---|
| 1 | Raj | 82 | A | 101 |
| 2 | Sara | 55 | C | 101 |
| 3 | Amit | 91 | NA | 101 |
Problem 3 — Alter the table
Add an Age column to STUDENT, then add a CHECK constraint so Age must be at least 17.
-- Solution 3
ALTER TABLE STUDENT ADD Age INT;
ALTER TABLE STUDENT ADD CONSTRAINT chk_age CHECK (Age >= 17);
Problem 4 — Update with a rule
Set Grade to 'A' for every student scoring more than 90 marks.
-- Solution 4 (this promotes Amit, 91 marks, to grade A)
UPDATE STUDENT SET Grade = 'A' WHERE Marks > 90;
Problem 5 — Delete, then clean up
Remove students scoring below 60. Then write the commands to (a) empty STUDENT keeping its structure, and (b) delete the table entirely.
-- Solution 5
DELETE FROM STUDENT WHERE Marks < 60; -- removes Sara (55)
TRUNCATE TABLE STUDENT; -- (a) empties rows, keeps the table
DROP TABLE STUDENT; -- (b) removes the table completely
You used CREATE with five constraint types, INSERT (including a DEFAULT), ALTER (add column + add constraint), UPDATE with a condition, and DELETE / TRUNCATE / DROP — the entire DDL + DML core in one workflow.
Command Cheat Sheet
| Command | Family | Job | Skeleton |
|---|---|---|---|
| CREATE TABLE | DDL | Build a table | CREATE TABLE t (col type constraint, …) |
| ALTER TABLE | DDL | Change structure | ALTER TABLE t ADD / MODIFY / DROP … |
| DROP TABLE | DDL | Delete table + data | DROP TABLE t |
| TRUNCATE TABLE | DDL | Empty all rows | TRUNCATE TABLE t |
| INSERT | DML | Add rows | INSERT INTO t VALUES (…) |
| UPDATE | DML | Change rows | UPDATE t SET col = v WHERE … |
| DELETE | DML | Remove rows | DELETE FROM t WHERE … |
Common Mistakes to Avoid
No WHERE means the command hits every row. Always confirm the condition first — there is no undo for an auto-committed change.
DELETE removes chosen rows (DML, reversible); TRUNCATE empties the table (DDL, fast); DROP destroys the table itself (DDL, gone for good).
A foreign key value must already exist in the parent table. Insert DEPARTMENT (or COURSE) rows before the EMPLOYEE (or STUDENT) rows that reference them.