When you need to enforce business rules or validate data in MySQL triggers, you'll want to raise custom exceptions. MySQL provides the SIGNAL statement for this purpose. Here's how to use it effectively.
The basic syntax is straightforward:
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Your custom error message';
SQLSTATE codes from '45000' to '49999' are reserved for user-defined errors. When SIGNAL is executed, it immediately stops the current operation and rolls back the transaction.
A common use case is preventing invalid data from being inserted:
DELIMITER $$
CREATE TRIGGER prevent_negative_salary
BEFORE INSERT ON employees
FOR EACH ROW
BEGIN
IF NEW.salary < 0 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Salary cannot be negative';
END IF;
END$$
DELIMITER ;
Now if someone tries to insert a negative salary, they'll get your custom error message and the insert will be blocked.
Enforce business rules like minimum age requirements:
DELIMITER $$
CREATE TRIGGER validate_employee_age
BEFORE INSERT ON employees
FOR EACH ROW
BEGIN
IF NEW.age < 18 THEN
SIGNAL SQLSTATE '45001'
SET MESSAGE_TEXT = 'Employee must be at least 18 years old';
END IF;
END$$
DELIMITER ;
Notice I used '45001' instead of '45000'. Using different SQLSTATE codes helps you identify which validation failed when debugging.
You can perform more complex validation by querying other tables:
DELIMITER $$
CREATE TRIGGER check_department_budget
BEFORE INSERT ON employee_assignments
FOR EACH ROW
BEGIN
DECLARE current_budget DECIMAL(10,2);
DECLARE total_salaries DECIMAL(10,2);
DECLARE new_salary DECIMAL(10,2);
-- Get department budget
SELECT budget INTO current_budget
FROM departments
WHERE department_id = NEW.department_id;
-- Get current total salaries
SELECT COALESCE(SUM(salary), 0) INTO total_salaries
FROM employees e
JOIN employee_assignments ea ON e.employee_id = ea.employee_id
WHERE ea.department_id = NEW.department_id;
-- Get new employee's salary
SELECT salary INTO new_salary
FROM employees
WHERE employee_id = NEW.employee_id;
-- Check if we'd exceed budget
IF (total_salaries + new_salary) > current_budget THEN
SIGNAL SQLSTATE '45002'
SET MESSAGE_TEXT = 'Adding this employee would exceed department budget';
END IF;
END$$
DELIMITER ;
I typically organize my error codes like this:
After creating a trigger, test it to make sure it works:
-- This should fail with your custom error
INSERT INTO employees (name, salary, age)
VALUES ('John Doe', -5000, 25);
-- Error: Salary cannot be negative
-- This should also fail
INSERT INTO employees (name, salary, age)
VALUES ('Jane Doe', 50000, 16);
-- Error: Employee must be at least 18 years old
If your trigger isn't working as expected:
SHOW TRIGGERS FROM your_database;Use database constraints for:
Use SIGNAL in triggers for:
Please donate if helpful