Triggers

PUBLISHED: MAY 2, 2026โ€ข5 MIN READ

Master SQL Triggers to automate database tasks. Learn how to use BEFORE and AFTER triggers for data validation, auditing, and logging with clear syntax examples and best practices.

Abhishek Singh Rajput
Abhishek SinghAuthor
nidoqueen
#031
nidoqueen

Triggers

๐Ÿ“Œ Database Triggers โ€“ Quick Notes & MCQs (with Solutions)

โœ… Basic Trigger Syntax

sql

CREATE TRIGGER trigger_name
{BEFORE | AFTER} {INSERT | UPDATE | DELETE}
ON table_name
FOR EACH ROW
BEGIN
-- trigger actions
END;

๐Ÿง  Key Points to Remember

Concept

Explanation

Trigger Timing

Can be BEFORE or AFTER an event.

Trigger Event

Can be INSERT, UPDATE, or DELETE.

FOR EACH ROW

Trigger executes once for every affected row.

OLD & NEW Keywords

OLD โ†’ data before change (UPDATE/DELETE)
NEW โ†’ data after change (INSERT/UPDATE)

Delimiter

In MySQL CLI, use DELIMITER // to handle BEGIN...END.

Restrictions

โŒ Cannot use COMMIT / ROLLBACK inside triggers
๐Ÿšซ Cannot call triggers manually

Common Use Cases

Logging, auditing, validation, enforcing business rules

๐Ÿงช MCQs Based on Real Accenture Technical Assessment

1๏ธโƒฃ Student Record Backup

Tables:

sql

students(student_id INT PRIMARY KEY, name VARCHAR(50), department VARCHAR(50))
student_backup(student_id INT, name VARCHAR(50), department VARCHAR(50), deleted_on DATETIME)

Question:
Backup every deleted student record into student_backup.

โœ… Correct Trigger:

sql

CREATE TRIGGER after_student_delete
AFTER DELETE ON students
FOR EACH ROW
BEGIN
INSERT INTO student_backup (student_id, name, department, deleted_on)
VALUES (OLD.student_id, OLD.name, OLD.department, NOW());
END;

โœ” Answer: AFTER DELETE using OLD values.

2๏ธโƒฃ Salary Update Log

sql

employees(emp_id INT PRIMARY KEY, salary DECIMAL(10,2))
salary_log(emp_id INT, old_salary DECIMAL(10,2), new_salary DECIMAL(10,2), updated_on DATETIME)

Log whenever salary changes.

โœ… Trigger:

sql

CREATE TRIGGER after_salary_update
AFTER UPDATE ON employees
FOR EACH ROW
BEGIN
INSERT INTO salary_log (emp_id, old_salary, new_salary, updated_on)
VALUES (OLD.emp_id, OLD.salary, NEW.salary, NOW());
END;

โœ” Answer: AFTER UPDATE with OLD & NEW.

3๏ธโƒฃ New Employee Registration Log

sql

employees(emp_id INT PRIMARY KEY, emp_name VARCHAR(50))
register_log(emp_id INT, joined_on DATETIME)

โœ… Trigger:

sql

CREATE TRIGGER after_employee_insert
AFTER INSERT ON employees
FOR EACH ROW
BEGIN
INSERT INTO register_log (emp_id, joined_on)
VALUES (NEW.emp_id, NOW());
END;

โœ” Answer: AFTER INSERT using NEW.

4๏ธโƒฃ Product Deletion Tracker

sql

products(prod_id INT PRIMARY KEY, prod_name VARCHAR(50))
product_log(prod_id INT, deleted_at DATETIME)

โœ… Trigger:

sql

CREATE TRIGGER after_product_delete
AFTER DELETE ON products
FOR EACH ROW
BEGIN
INSERT INTO product_log (prod_id, deleted_at)
VALUES (OLD.prod_id, NOW());
END;

โœ” Answer: AFTER DELETE.

5๏ธโƒฃ Validate Order Total Before Insert

sql

orders(order_id INT PRIMARY KEY, total_amount DECIMAL(10,2))

โ— Total must not be negative.

โœ… Trigger:

sql

CREATE TRIGGER before_order_insert
BEFORE INSERT ON orders
FOR EACH ROW
BEGIN
IF NEW.total_amount < 0 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Total amount cannot be negative';
END IF;
END;

โœ” Answer: BEFORE INSERT with validation.

โœ” Answer:ย SIGNAL SQLSTATE terminate the query and show an error message

6๏ธโƒฃ Attendance Update Monitor

sql

attendance(stud_id INT, percentage INT)
attendance_log(stud_id INT, old_percent INT, new_percent INT, updated_on DATETIME)

โœ… Trigger:

sql

CREATE TRIGGER after_attendance_update
AFTER UPDATE ON attendance
FOR EACH ROW
BEGIN
INSERT INTO attendance_log (stud_id, old_percent, new_percent, updated_on)
VALUES (OLD.stud_id, OLD.percentage, NEW.percentage, NOW());
END;

โœ” Answer: AFTER UPDATE.

7๏ธโƒฃ Prevent Deletion of Admin Users

sql

users(user_id INT PRIMARY KEY, role VARCHAR(20))

โœ… Trigger:

sql

CREATE TRIGGER before_user_delete
BEFORE DELETE ON users
FOR EACH ROW
BEGIN
IF OLD.role = 'Admin' THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Cannot delete Admin users';
END IF;
END;

โœ” Answer: BEFORE DELETE to block action.

8๏ธโƒฃ Log Department Change Only If Changed

sql

employees(emp_id INT, department VARCHAR(50))
dept_change_log(emp_id INT, old_dept VARCHAR(50), new_dept VARCHAR(50), updated_on DATETIME)

โœ… Trigger:

sql

CREATE TRIGGER after_dept_update
AFTER UPDATE ON employees
FOR EACH ROW
BEGIN
IF OLD.department <> NEW.department THEN
INSERT INTO dept_change_log (emp_id, old_dept, new_dept, updated_on)
VALUES (OLD.emp_id, OLD.department, NEW.department, NOW());
END IF;
END;

โœ” Answer: AFTER UPDATE (log when changed).

9๏ธโƒฃ Customer Insertion Tracker

sql

customers(cust_id INT PRIMARY KEY, cust_name VARCHAR(50))
customer_log(cust_id INT, created_on DATETIME)

โœ… Trigger:

sql

CREATE TRIGGER after_customer_insert
AFTER INSERT ON customers
FOR EACH ROW
BEGIN
INSERT INTO customer_log (cust_id, created_on)
VALUES (NEW.cust_id, NOW());
END;

โœ” Answer: AFTER INSERT.

๐Ÿ”Ÿ Product Price Validation (Prevent Negative Price)

sql

products(prod_id INT, price DECIMAL(10,2))

โœ… Trigger:

sql

CREATE TRIGGER before_price_update
BEFORE UPDATE ON products
FOR EACH ROW
BEGIN
IF NEW.price < 0 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Price cannot be negative';
END IF;
END;

โœ” Answer: BEFORE UPDATE with validation.