In this tutorial, we will learn how to raise an error using the signal statement. The SIGNAL and RESIGNAL statements are very similar to each other except few points. We will see the details and examples of the SIGNAL statement in this article and for the RESIGNAL statement, we will have a separate tutorial.
Also read: MySQL Index Hints- FORCE INDEX
Introduction to MySQL SIGNAL
The SIGNAL statement is used to throw an error in the stored programs such as stored procedures, stored programs, triggers or events. Using the SIGNAL, you can return an error number, SQL STATE value or a custom message.
To execute the SIGNAL statement, you don’t need any special privilege.
In short, you can use the SIGNAL statement to return a custom message when an error occurs in the program.
Also read: Variables in MySQL Stored Procedures – Easy Implementation
MySQL SIGNAL Statement Syntax
The following syntax shows the correct way to use the SIGNAL statement-
Code language: SQL (Structured Query Language) (sql)
SIGNAL condition_value [SET signal_information_item [, signal_information_item] ...] condition_value: { SQLSTATE [VALUE] sqlstate_value | condition_name } signal_information_item: condition_information_item_name = simple_value_specification
Here,
The condition_value tells the error value to be thrown. The condtion_value can be an SQLSTATE or a condition_name which refers to the previously created named definition with the DECLARE … CONDITION statement.
The SQLSTATE value for a SIGNAL statement shouldn’t begin with the number “00” because these values imply success rather than an error. Instead, they should begin with a value other than ’00’. Either the SQLSTATE value is explicitly provided in the SIGNAL statement or it is referenced by a named condition in the statement, but either way, it is true. A Bad SQLSTATE problem manifests itself when the value is incorrect.
Optionally, the SIGNAL statement includes a SET clause with a list of condition information item name = simple_value_specification assignments, separated by commas, for each signal item.
Use the code “45000,” which stands for “unhandled user-defined exception,” to indicate a generic SQLSTATE value.
MySQL SIGNAL Statement Examples
Now we will take some examples to demonstrate the use of the SIGNAL statement.
Here, we will create a procedure to show the use of warnings and errors with the signal statement.
Code language: SQL (Structured Query Language) (sql)
DROP PROCEDURE IF EXISTS signalDemo; DELIMITER // CREATE PROCEDURE signalDemo(num INT) BEGIN IF num = 0 THEN SIGNAL SQLSTATE '01000'; ELSEIF num = 1 THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT="error raised 1"; ELSEIF num = 2 THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT="error raised 2"; ELSE SIGNAL SQLSTATE '01000' SET MESSAGE_TEXT="warning raised" , MYSQL_ERRNO = 1000; END IF; END; // DELIMITER ;
Here, if the value of num is 0, the procedure will signal a warning because the SQLSTATE value that starts with ’01’ is the warning.
Note that, the warning doesn’t terminate the procedure.
When the value of num is 1 or 2, the procedure signals an error and sets the message_text item. Here, after the error is caught, the procedure terminates and the text that you set earlier will be displayed.
If the value of num is anything else, the procedure signals the warning and sets the custom message with the error number.
Let’s examine everything by calling the procedures.
Code language: SQL (Structured Query Language) (sql)
CALL signalDemo(0);
Code language: SQL (Structured Query Language) (sql)
CALL signalDemo(1); CALL signalDemo(2);
CALL signalDemo(3);
Code language: SQL (Structured Query Language) (sql)
A specific SQLSTATE value is used to signal the condition if the SIGNAL statement specifies that value.
Let’s take an example of divide by zero error.
Code language: SQL (Structured Query Language) (sql)
DROP PROCEDURE IF EXISTS div_by_zero; DELIMITER // CREATE PROCEDURE div_by_zero(divisor INT) BEGIN IF divisor = 0 THEN SIGNAL SQLSTATE '22012'; END IF; END; // DELIMITER ;
You can also give them a name to the signal statement. If you do so, the condition must be defined using the SQLSTATE value instead of the MySQL error number.
Let’s re-write the above procedure using the named signal statement.
Code language: SQL (Structured Query Language) (sql)
DROP PROCEDURE IF EXISTS div_by_zero; DELIMITER // CREATE PROCEDURE div_by_zero(divisor INT) BEGIN DECLARE div_by_zero_error CONDITION FOR SQLSTATE '22012'; IF divisor = 0 THEN SIGNAL div_by_zero_error; END IF; END; // DELIMITER ;
Summary
In this tutorial, we have learned about the SIGNAL statement in MySQL. It is a broad topic to learn and understand. However, it is one of the most important topics in MySQL. It is absolutely worth learning the SIGNAL topic. If you want to get a more detailed view of the SIGNAL, you can check out its official documentation.
References
MySQL official documentation on the SIGNAL.
Unfortunately, the (outdated) mysql_* extension in PHP does not support exception handling.
Obviously, this is an issue for those of us who want to avail of the flexibility that exceptions can offer. For the most part, developers who use the mysql_* extension tend to carry out their “error handling” like so:
mysql_query($sql, $connection) or die(mysql_error($connection));
The problem with this approach is that the rest of our application is completely oblivious to any SQL errors that may occur. If the query fails, the script is halted and there is no way to recover. To make matters even worse, the user will be presented with a nasty-looking SQL error.
A better, more-flexible approach would be to throw an exception if the query fails:
$result = mysql_query($sql, $connection); if($result === false){ throw new Exception(mysql_error($connection)); }
The code above checks to see if mysql_query returns a boolean FALSE value. If it does, we assume that an error has occurred. If an error has occurred, we proceed to throw an Exception containing the MySQL error message.
If you’re worried about the extra added code, then you can abstract your exception-throwing into a custom function like so:
function query($sql, $conn = null){ $res = mysql_query($sql, $conn); if($res === false){ throw new Exception(mysql_error($conn)); } return $res; }
Using this custom function, we can execute our queries like so (and catch any errors):
try{ query("SELECT name FROM users", $connection); } catch(Exception $e){ //Failed }
Using exceptions can be extremely beneficial when it comes to handling failed SQL queries.
In the vast majority of cases, a failed SQL query indicates that the application is down and that something has gone terribly wrong. In cases like this, shouldn’t catch the exception in question. Instead, you should “handle” it via a custom exception handler. This can be achieved with the function set_exception_handler. An example:
function app_error($exception) { header("HTTP/1.1 500 Internal Server Error"); custom_log_function($exception->getMessage()); include 'template/error.html'; exit; } set_exception_handler('app_error');
Basically, whenever an exception is thrown, our application will automatically call the app_error function above. There, we can log the error, set a 500 internal server error header and provide the user with a custom “error template”.
This article is half-done without your Comment! *** Please share your thoughts via Comment ***
In this post, I am sharing the full demonstration on how to manage error/exception handling in the Stored Procedure of MySQL.
Whenever an exception is occurring in a stored procedure, it is very important to handle it by showing proper error messages.
If you do not handle the exception, there would be a chance to fail application with the certain exception in a stored procedure.
If you get an error in stored procedure, instead of an exit, you should continue without any error message. That means you can show any default or custom error code or message to the application/user.
MySQL provides Handler to handle the exception in the stored procedure.
Below is a full demonstration of a handler with examples:
/*Create Employee database for demo */ CREATE DATABASE Employee; /*Create sample EmployeeDetails table.*/ CREATE TABLE Employee.tbl_EmployeeDetails ( EmpID INTEGER ,EmpName VARCHAR(50) ,EmailAddress VARCHAR(50) ,CONSTRAINT pk_tbl_EmployeeDetails_EmpID PRIMARY KEY (EmpID) )ENGINE = InnoDB; |
How to declare handler in store procedure:
Syntax of Handler:
DECLARE handler_action HANDLER FOR condition_value … statement |
Three type of Handler_Action:
- CONTINUE
- EXIT
- UNDO
Type of Condition Value:
- mysql_error_code
- sqlstate_value
- SQLWarning
- SQLException
- NotFound
How to write handler in stored procedure?
E.g.
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SELECT ‘Error occured’; DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET IsError=1; DECLARE EXIT HANDLER FOR SQLEXCEPTION SET IsError=1; DECLARE EXIT HANDLER FOR SQLSTATE ‘23000’ SET IsError = 1; |
The Above are four different handler examples. Now, I am going to insert a duplicate value into EmpID column.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
DELIMITER // CREATE PROCEDURE Employee.usp_InsertEmployeeDetails ( InputEmpID INTEGER ,InputEmpName VARCHAR(50) ,InputEmailAddress VARCHAR(50) ) /**************************************************************** Authors Name : Anvesh Patel Created Date : 2015-05-20 Description : This is demo stored procedure to insert record into table with proper error handling.Basically for www.dbrnd.com readers. *****************************************************************/ BEGIN DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SELECT ‘Error occured’; INSERT INTO Employee.tbl_EmployeeDetails ( EmpID ,EmpName ,EmailAddress ) VALUES ( InputEmpID ,InputEmpName ,InputEmailAddress ); SELECT *FROM Employee.tbl_EmployeeDetails; END // DELIMITER ; |
In the above SP, I defined a CONTINUE handler with my custom exception message.
Now, call the above SP two times with same EmpID.
The first time, it will execute successfully, but the second time it will throw a custom error message.
As we defined CONTINUE handler, so it will just show an error message and CONTINUE to next part of the SELECT statement.
Let’s See,
CALL Employee.usp_InsertEmployeeDetails (1,’Anvesh’,’anvesh@gmail.com’); CALL Employee.usp_InsertEmployeeDetails (1,’Roy’,’Roy@gmail.com’); |
Above are the two different calls with same EmpID value. The first call executes without any error message and the second call execute with an error message.
The resule of Second Call:
As we defined CONTINUE, so you can find two results in above image. One is our custom error message and second is the result of the defined SELECT statement.
The execution didn’t stop by error, and it continued for another part.
Now, check the EXIT handler:
Please modify your handler and replace CONTINUE by EXIT:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
DELIMITER // CREATE PROCEDURE Employee.usp_InsertEmployeeDetails ( InputEmpID INTEGER ,InputEmpName VARCHAR(50) ,InputEmailAddress VARCHAR(50) ) /***************************************************************** Authors Name : Anvesh Patel Created Date : 2015-05-20 Description : This is demo stored procedure to insert record into table with proper error handling.Basically for www.dbrnd.com readers. ******************************************************************/ BEGIN DECLARE EXIT HANDLER FOR SQLEXCEPTION SELECT ‘Error occured’; INSERT INTO Employee.tbl_EmployeeDetails ( EmpID ,EmpName ,EmailAddress ) VALUES ( InputEmpID ,InputEmpName ,InputEmailAddress ); SELECT *FROM Employee.tbl_EmployeeDetails; END // DELIMITER ; |
Call with the same parameter:
CALL Employee.usp_InsertEmployeeDetails (1,’Roy’,’Roy@gmail.com’); |
The Result is an only error message, and you cannot find two results as we defined EXIT to exit the code when an error occurred.
The best practice is to create a output parameter and store 1 if any error occurred.
Application code has to check this output parameter is NULL or 1.
1 = Error.
NULL = No Error.
Below is a stored procedure for this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
DELIMITER // CREATE PROCEDURE Employee.usp_InsertEmployeeDetails ( InputEmpID INTEGER ,InputEmpName VARCHAR(50) ,InputEmailAddress VARCHAR(50) ,out IsError INTEGER ) /*********************************************************** Authors Name : Anvesh Patel Created Date : 2015-05-20 Description : This is demo stored procedure to insert record into table with proper error handling. Basically for www.dbrnd.com readers. ************************************************************/ BEGIN DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET IsError=1; INSERT INTO Employee.tbl_EmployeeDetails ( EmpID ,EmpName ,EmailAddress ) VALUES ( InputEmpID ,InputEmpName ,InputEmailAddress ); SELECT *FROM Employee.tbl_EmployeeDetails; END // DELIMITER ; |
Now call the above SP and select output parameter:
CALL Employee.usp_InsertEmployeeDetails (1,’Roy’,’Roy@gmail.com’,@IsError); SELECT @IsError; |
Now Results are:
Above is a simple demonstration of Error Handling in MySQL. You can also use SQLSTATE which shows default error messages of MySQL.
May 21, 2015