SQL Error Handling — Catching and Responding to SQL Failures: BEGIN...HANDLER, SIGNAL
Handle SQL Errors
The office attempts to add a repeated roll number. Silently continuing could make the application claim a student was saved when the insert failed.
Database error handling determines how a program responds when an operation fails. A handler must match the intended condition and leave the data in an understood state.
Explain and apply
Handle an expected MySQL database error and explain what happens to the operation and transaction.
Work it out
Predict what remains after an insertion conflicts with the primary key. The original three rows should still be present.
Avoid mistakes
An EXIT handler does not by itself roll back the entire transaction.
Handle SQL Errors: the request and its result
School need
The office attempts to add a repeated roll number. Silently continuing could make the application claim a student was saved when the insert failed.
Database operation
Database error handling determines how a program responds when an operation fails. A handler must match the intended condition and leave the data in an understood state.
Check the outcome
The duplicate-key insert is rejected. This SQLite fixture verifies the constraint failure and surviving data; MySQL handler definitions in the preserved examples require a MySQL server.
Understand what the database does
MySQL DECLARE HANDLER associates conditions with a response. CONTINUE resumes after handling; EXIT leaves the declaring compound block. SIGNAL can raise an explicit application condition. A routine should distinguish expected exceptions from failures that require rollback or propagation.
Related concepts: Data Constraints and Transactions and Stored Procedures.
What is Error Handling in SQL?
Error handling allows you to catch and manage exceptions inside stored procedures or triggers using constructs like DECLARE HANDLER, SIGNAL, and RESIGNAL. These tools help you respond smartly instead of failing silently or abruptly.
Syntax Overview
DECLARE CONTINUE HANDLER– catches errors and continuesDECLARE EXIT HANDLER– catches errors and exits the blockSIGNAL SQLSTATE– manually raise a custom error
Sample Table – students
SQL · portable concepts; preserved examples identify their engine
CREATE TABLE students (
roll_no INT PRIMARY KEY,
name VARCHAR(50),
marks INT
);
INSERT INTO students VALUES
(1, 'Aarav Sharma', 85),
(2, 'Diya Iyer', 92);
1. Handling Duplicate Entry Error (EXIT HANDLER)
SQL · portable concepts; preserved examples identify their engine
DELIMITER $$
CREATE PROCEDURE insert_student (
IN p_roll INT,
IN p_name VARCHAR(50),
IN p_marks INT
)
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
SELECT 'Error: Roll number already exists or invalid data.' AS message;
END;
INSERT INTO students VALUES (p_roll, p_name, p_marks);
END$$
DELIMITER ;
Test it:
CALL insert_student(1, 'Sneha Patil', 88);
message
---------------------------------------
Error: Roll number already exists or invalid data.
2. Handling Error and Continuing Execution (CONTINUE HANDLER)
SQL · portable concepts; preserved examples identify their engine
DELIMITER $$
CREATE PROCEDURE insert_and_continue ()
BEGIN
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
SELECT 'Attempted insert failed, moving on...' AS status;
END;
INSERT INTO students VALUES (1, 'Mehul', 75); -- Will fail
SELECT * FROM students;
END$$
DELIMITER ;
Call it:
CALL insert_and_continue();
status
-------------------------------
Attempted insert failed, moving on...
roll_no | name | marks
--------+----------------+-------
1 | Aarav Sharma | 85
2 | Diya Iyer | 92
3. Raising a Custom Error with SIGNAL
Input definitions and data for this example. The shown statements establish the base fixture. Where this section changes an existing object, its required object definition is included below; use the stated before/after table to follow a sequence of changes.
CREATE TABLE students (
roll_no INT PRIMARY KEY,
name VARCHAR(50),
marks INT
);
INSERT INTO students VALUES
(1, 'Aarav Sharma', 85),
(2, 'Diya Iyer', 92);
SQL · portable concepts; preserved examples identify their engine
DELIMITER $$
CREATE PROCEDURE validate_marks (
IN p_marks INT
)
BEGIN
IF p_marks > 100 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Marks cannot exceed 100';
END IF;
SELECT CONCAT('Accepted: ', p_marks) AS status;
END$$
DELIMITER ;
Try invalid input:
CALL validate_marks(105);
ERROR 1644 (45000): Marks cannot exceed 100
Best Practices
Query discussed in this section:
CALL validate_marks(105);
- Use EXIT HANDLER to stop on fatal errors.
- Use CONTINUE HANDLER to skip errors but continue processing.
- Use SIGNAL to enforce custom validation rules clearly.
- Always log or alert on exceptions — don’t fail silently.
Real-World School Use Cases
- Prevent marks from exceeding limits (custom SIGNAL)
- Log failed insertions or updates (HANDLER + log table)
- Auto-handle missing attendance records without breaking flows
Important differences and mistakes
An EXIT handler does not by itself roll back the entire transaction. A duplicate-key error is not equivalent to every integrity violation. Do not swallow an error and report success; decide explicitly which writes remain valid.
Try it with the school data
Predict what remains after an insertion conflicts with the primary key. The original three rows should still be present.
This practice uses a separate, fresh fixture named practice_students. It does not continue the changing table state of the earlier examples.
| roll_no | name | class | marks | city |
|---|---|---|---|---|
| 1 | Aarav | 10A | 85 | Pune |
| 2 | Diya | 9B | 70 | Chennai |
| 3 | Sneha | 10A | 85 | Pune |
SQL · create only these practice tables in a disposable database:
CREATE TABLE practice_students (roll_no INTEGER PRIMARY KEY, name VARCHAR(50), class VARCHAR(10), marks INTEGER, city VARCHAR(30));
INSERT INTO practice_students VALUES
(1, 'Aarav', '10A', 85, 'Pune'),
(2, 'Diya', '9B', 70, 'Chennai'),
(3, 'Sneha', '10A', 85, 'Pune');
Worked answer and reasoning
This practice uses a separate, fresh fixture named practice_students. It does not continue the changing table state of the earlier examples.
| roll_no | name | class | marks | city |
|---|---|---|---|---|
| 1 | Aarav | 10A | 85 | Pune |
| 2 | Diya | 9B | 70 | Chennai |
| 3 | Sneha | 10A | 85 | Pune |
SQL · create only these practice tables in a disposable database:
CREATE TABLE practice_students (roll_no INTEGER PRIMARY KEY, name VARCHAR(50), class VARCHAR(10), marks INTEGER, city VARCHAR(30));
INSERT INTO practice_students VALUES
(1, 'Aarav', '10A', 85, 'Pune'),
(2, 'Diya', '9B', 70, 'Chennai'),
(3, 'Sneha', '10A', 85, 'Pune');
SQL · this practice variation runs with SQLite 3; the preserved examples retain their stated dialect
INSERT INTO practice_students VALUES (1, 'Another student', '9B', 90, 'Delhi');
SELECT COUNT(*) AS student_rows FROM practice_students;| student_rows |
|---|
| 3 |
The duplicate-key insert is rejected. This SQLite fixture verifies the constraint failure and surviving data; MySQL handler definitions in the preserved examples require a MySQL server.
The marked INSERT is expected to fail. Observe that error before running the following SELECT; do not report that the insert succeeded.
Check your understanding
Use the idea independently
Database error handling determines how a program responds when an operation fails. A handler must match the intended condition and leave the data in an understood state.
The duplicate-key insert is rejected. This SQLite fixture verifies the constraint failure and surviving data; MySQL handler definitions in the preserved examples require a MySQL server.
Continue your understanding with Data Constraints and Transactions and Stored Procedures.
Source for the engine-specific behavior: MySQL 8.4 reference documentation.
Reaching the recap and completing the quizzes are separate milestones.