A DELETE trigger automatically runs some actions right after or before a row is deleted from a table. It helps keep data safe or update related information without doing it manually.
You want to log every time a record is deleted from a table.
You need to update another table when a row is removed.
You want to prevent deletion if certain conditions are not met.
You want to clean up related data in other tables automatically.
You want to keep track of who deleted data and when.
Syntax
SQL
CREATE TRIGGER trigger_name
BEFORE DELETEON table_name
FOR EACH ROW
BEGIN
-- SQL statements hereEND;
CREATE TRIGGER trigger_name
AFTER DELETEON table_name
FOR EACH ROW
BEGIN
-- SQL statements hereEND;
Use BEFORE DELETE to run the trigger before the row is deleted.
Use AFTER DELETE to run the trigger after the row is deleted.
Examples
This trigger logs the ID and time whenever an employee is deleted.
SQL
CREATE TRIGGER log_delete
AFTER DELETEON employees
FOR EACH ROW
BEGIN
INSERTINTO deleted_log(employee_id, deleted_at)
VALUES (OLD.id, CURRENT_TIMESTAMP);
END;
This trigger stops deletion of orders that are already shipped.
SQL
CREATE TRIGGER prevent_delete
BEFORE DELETEON orders
FOR EACH ROW
BEGIN
IF OLD.status = 'shipped'THEN
SIGNAL SQLSTATE '45000'SET MESSAGE_TEXT = 'Cannot delete shipped orders';
END IF;
END;
Sample Program
This example creates two tables and a DELETE trigger. When an employee is deleted, the trigger logs the employee's ID and deletion time into deleted_log. Then it deletes employee with ID 1 and shows the log.
SQL
CREATETABLE employees (
id INTPRIMARYKEY,
name VARCHAR(50)
);
CREATETABLE deleted_log (
employee_id INT,
deleted_at TIMESTAMP
);
DELIMITER $$
CREATE TRIGGER log_delete
AFTER DELETEON employees
FOR EACH ROW
BEGIN
INSERTINTO deleted_log(employee_id, deleted_at)
VALUES (OLD.id, CURRENT_TIMESTAMP);
END$$
DELIMITER ;
INSERTINTO employees VALUES (1, 'Alice'), (2, 'Bob');
DELETEFROM employees WHERE id = 1;
SELECT * FROM deleted_log;
OutputSuccess
Important Notes
In triggers, OLD refers to the row before deletion.
Not all databases support triggers exactly the same way; check your database docs.
Use triggers carefully to avoid slowing down your database operations.
Summary
DELETE triggers run automatically when rows are deleted.
They help automate tasks like logging or preventing unwanted deletes.
Use BEFORE DELETE or AFTER DELETE depending on when you want the trigger to run.
Practice
(1/5)
1. What is the main purpose of a DELETE trigger in a database?
easy
A. To insert new rows into a table
B. To update rows before they are deleted
C. To automatically run code when rows are deleted from a table
D. To prevent any data from being deleted
Solution
Step 1: Understand what triggers do
Triggers run automatically in response to certain database events like insert, update, or delete.
Step 2: Focus on DELETE triggers
A DELETE trigger specifically runs when rows are deleted, allowing automatic actions during that event.
Final Answer:
To automatically run code when rows are deleted from a table -> Option C
Quick Check:
DELETE trigger = runs on row deletion [OK]
Hint: DELETE triggers run code automatically on row deletions [OK]
Common Mistakes:
Confusing DELETE triggers with INSERT triggers
Thinking DELETE triggers prevent deletion by default
Assuming DELETE triggers update rows instead
2. Which of the following is the correct syntax to create a trigger that runs before a row is deleted from a table named Employees?
easy
A. CREATE TRIGGER before_delete_employee DELETE ON Employees FOR EACH ROW BEGIN --code END;
B. CREATE TRIGGER before_delete_employee AFTER DELETE ON Employees FOR EACH ROW BEGIN --code END;
C. CREATE TRIGGER before_delete_employee ON Employees BEFORE DELETE FOR EACH ROW BEGIN --code END;
D. CREATE TRIGGER before_delete_employee BEFORE DELETE ON Employees FOR EACH ROW BEGIN --code END;
Solution
Step 1: Identify correct trigger timing syntax
The syntax for a BEFORE DELETE trigger includes 'BEFORE DELETE ON TableName'.
Step 2: Check full syntax correctness
CREATE TRIGGER before_delete_employee BEFORE DELETE ON Employees FOR EACH ROW BEGIN --code END; correctly uses 'CREATE TRIGGER name BEFORE DELETE ON Employees FOR EACH ROW BEGIN ... END;'. Others misuse order or keywords.
Final Answer:
CREATE TRIGGER before_delete_employee BEFORE DELETE ON Employees FOR EACH ROW BEGIN --code END; -> Option D
Quick Check:
BEFORE DELETE ON Table = correct syntax [OK]
Hint: Use BEFORE DELETE ON table for pre-delete triggers [OK]
Common Mistakes:
Placing BEFORE DELETE after ON table
Omitting FOR EACH ROW clause
Using DELETE ON instead of BEFORE DELETE ON
3. Given the following trigger and table data, what will be the output after deleting the row with id = 2 from Orders?
CREATE TRIGGER log_delete AFTER DELETE ON Orders
FOR EACH ROW
BEGIN
INSERT INTO DeletedOrdersLog(order_id, deleted_at) VALUES (OLD.id, CURRENT_TIMESTAMP);
END;
-- Initial Orders table:
-- id | product
-- 1 | Book
-- 2 | Pen
-- 3 | Notebook
-- DeletedOrdersLog is initially empty.
medium
A. A new row with order_id = 2 is inserted into DeletedOrdersLog
B. The row with id = 2 is restored in Orders
C. No changes happen to DeletedOrdersLog
D. An error occurs because OLD.id is invalid
Solution
Step 1: Understand AFTER DELETE trigger behavior
The trigger runs after a row is deleted from Orders, so OLD.id refers to the deleted row's id.
Step 2: Analyze trigger action
The trigger inserts a new row into DeletedOrdersLog with order_id = OLD.id (2) and current timestamp.
Final Answer:
A new row with order_id = 2 is inserted into DeletedOrdersLog -> Option A
Quick Check:
AFTER DELETE inserts log row with OLD.id [OK]
Hint: AFTER DELETE triggers can log deleted row info using OLD [OK]
Common Mistakes:
Thinking OLD.id is not accessible in DELETE triggers
Assuming trigger restores deleted rows
Believing no action happens after delete
4. Consider this trigger code snippet intended to prevent deletion of rows from Users table if the user is an admin:
CREATE TRIGGER prevent_admin_delete BEFORE DELETE ON Users
FOR EACH ROW
BEGIN
IF OLD.role = 'admin' THEN
SIGNAL SQLSTATE '45000' MESSAGE_TEXT = 'Cannot delete admin user';
END IF;
END;
What is the main issue if this trigger does not prevent admin deletions?
medium
A. The SIGNAL statement syntax is incorrect
B. The condition should check NEW.role instead of OLD.role
C. The trigger does not specify FOR EACH ROW
D. The trigger should be AFTER DELETE, not BEFORE DELETE
Solution
Step 1: Check trigger timing and row context
BEFORE DELETE and FOR EACH ROW are correctly used to check OLD.role before deletion.
Step 2: Verify SIGNAL syntax
In standard SQL, SIGNAL syntax requires correct SQLSTATE and message format. If syntax is wrong, error won't raise and deletion proceeds.
Final Answer:
The SIGNAL statement syntax is incorrect -> Option A
Quick Check:
SIGNAL syntax error prevents trigger from blocking delete [OK]
Hint: Check SIGNAL syntax carefully to block deletes [OK]
Common Mistakes:
Using AFTER DELETE instead of BEFORE DELETE
Checking NEW instead of OLD in DELETE triggers
Omitting FOR EACH ROW clause
5. You want to create a DELETE trigger on a Products table that archives deleted rows into an ArchivedProducts table, but only if the product price is above 100. Which trigger definition correctly implements this logic?
hard
A. CREATE TRIGGER archive_expensive_product BEFORE DELETE ON Products FOR EACH ROW BEGIN IF NEW.price > 100 THEN INSERT INTO ArchivedProducts (id, price) VALUES (NEW.id, NEW.price); END IF; END;
B. CREATE TRIGGER archive_expensive_product AFTER DELETE ON Products FOR EACH ROW BEGIN IF OLD.price > 100 THEN INSERT INTO ArchivedProducts (id, price) VALUES (OLD.id, OLD.price); END IF; END;
C. CREATE TRIGGER archive_expensive_product AFTER DELETE ON Products FOR EACH ROW BEGIN IF NEW.price > 100 THEN INSERT INTO ArchivedProducts (id, price) VALUES (OLD.id, OLD.price); END IF; END;
D. CREATE TRIGGER archive_expensive_product BEFORE DELETE ON Products FOR EACH ROW BEGIN IF NEW.price > 100 THEN INSERT INTO ArchivedProducts (id, price) VALUES (OLD.id, OLD.price); END IF; END;
Solution
Step 1: Choose correct timing and row reference
AFTER DELETE triggers run after deletion; OLD refers to deleted row data. BEFORE DELETE can also work but OLD is preferred after deletion.
Step 2: Check condition and insert logic
Condition must check OLD.price > 100. Insert must use OLD column values to archive deleted row data.
Step 3: Validate options
CREATE TRIGGER archive_expensive_product AFTER DELETE ON Products FOR EACH ROW BEGIN IF OLD.price > 100 THEN INSERT INTO ArchivedProducts (id, price) VALUES (OLD.id, OLD.price); END IF; END; uses AFTER DELETE, OLD.price, and inserts OLD.id, OLD.price correctly. Others use NEW or wrong timing.
Final Answer:
CREATE TRIGGER archive_expensive_product AFTER DELETE ON Products FOR EACH ROW BEGIN IF OLD.price > 100 THEN INSERT INTO ArchivedProducts (id, price) VALUES (OLD.id, OLD.price); END IF; END; -> Option B
Quick Check:
AFTER DELETE + OLD.price condition + insert OLD columns = correct [OK]
Hint: Use AFTER DELETE and OLD to archive deleted rows conditionally [OK]
Common Mistakes:
Using NEW instead of OLD in DELETE triggers
Placing condition on NEW.price which is invalid
Using BEFORE DELETE but referencing OLD incorrectly
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.