I can't seem to find anywhere how to catch and re-throw any errors or warnings that can occur in a procedure.
What I want is the syntax to do the following:
create procedure myProcedure()
begin
declare exit handler for ANYTHING_WRONG_THAT_CAN_BE_CAUGHT_WARNINGS_INCLUDED
begin
rollback;
RE_THROW THE_THING_THAT_WAS_CAUGHT;
end;
start transaction;
-- do some stuff
commit;
end; //
The reason being that I want to force a rollback on an error or warning but leave it up to the client to decide what to do with the specific error.
The all-cap areas are the portions where I do not know what to put.
Thanks for any help!
Edit -------
I have since learned it is not possible to do what I have asked :'(.
Instead I have a single error for anything that goes wrong and used the following code:
declare exit handler for sqlwarning, sqlexception begin
rollback;
call error();
end;
(error() does not exist)
To catch all SQL exceptions, use:
DECLARE EXIT HANDLER FOR SQLEXCEPTION
SQLWARNINGS can be used to catch warnings also.
Inside the exception handler, to raise the error or warning that was just caught, use:
RESIGNAL
See the documentation for the RESIGNAL statement:
http://dev.mysql.com/doc/refman/5.5/en/resignal.html
This is available since MySQL 5.5
Related
I have read the documentation on Exit Handlers and have found useful code ideas in relevant SO questions here and here amongst other places.
Nevertheless, calling the stored procedure below appears to complete OK and returns a TRUE value for the parameter success. when I know it is definitely not completing OK, not least because there was a syntax error in the body SQL (it was referring to a field that did not exist).
So the exit handler should have kicked in and returned FALSE for parameter success.
Can anyone help me to understand why a transaction that fails does not return the correct value for the parameter? (I suspect it has something to do with where I set success to true)
The actual SQL inside the transaction is not important to this question so I haven't shown it. Just assume that it might or might not successfully complete the transaction. It is the success or failure of that transaction that I want to detect through the parameter
DELIMITER $$
CREATE PROCEDURE do_thing (OUT success BOOLEAN)
DETERMINISTIC
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN SET success := FALSE; ROLLBACK; END; # rollback on any error
DECLARE EXIT HANDLER FOR SQLWARNING BEGIN SET success := FALSE; ROLLBACK; END; # rollback on any warning
START TRANSACTION;
< SQL that might cause an error >
< in my case it was referring to a field that didn't exist>
COMMIT;
SET success := TRUE;
END$$
DELIMITER ;
SEE DBFIDDLE
The first part is a copy of your code, it throws an error....
The second part is corrected, both DECLARE EXIT are moved within the block.
The third part is an example where #success will be set to false.
The following transaction runs no problem. However, once a transaction is failed, for example, column number doesn't match, or any other reason, it will only show an error message "'SQLWARNING: The request at Linux system time ${LINUX_SYSTEM_TIME} insert failed. Th data will be rollbacked'" but no error message to show the actual failure. May I know if there is any MySQL way to show an error message in a MySQL transaction? Thank you.
delimiter //
CREATE PROCEDURE 123
BEGIN
DECLARE EXIT HANDLER FOR SQLWARNING
BEGIN
ROLLBACK;
SELECT 'SQLWARNING: The request at Linux system time ${LINUX_SYSTEM_TIME} insert failed. Th data will be rollbacked';
END;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
SELECT 'The request at Linux system time ${LINUX_SYSTEM_TIME} insert failed. Th data will be rollbacked';
END;
START TRANSACTION;
<do whatever we need in transaction>
COMMIT;
END //
CALL 123;
DROP PROCEDURE IF EXISTS
Just to highlight the answer I kindly got from ##Solarflare. Resignal is an easy solution here (MySQL exception handler access exception being handled):
DECLARE EXIT HANDLER FOR SQLWARNING
BEGIN
ROLLBACK;
SELECT 'SQLWARNING: whatever error message';
RESIGNAL;
END;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
SELECT 'SQLWARNING: whatever error message;'
RESIGNAL;
END;
Turn on error logging. http://www.pontikis.net/blog/how-and-when-to-enable-mysql-logs has a good tutorial.
Is it possible to handle errors like inexistence of stored procedure and wrong number of params?
As I see, the handler like bellow doesn’t catch such errors :(
CREATE PROCEDURE _tmp_proc(
)
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
IF IFNULL(#LOG_LEVEL, 1) < 2 THEN
ROLLBACK;
END IF;
SELECT 'An error has occurred';
RESIGNAL;
END;
CALL inexisted_proc();
END
Is it possible to handle errors like inexistence of stored procedure
and wrong number of params?
Yes you can but it should be handled at the calling site and not in the procedure. With calling site, I mean your application end where you are calling the stored procedure. So if you are using PHP then use the error handling mechanism try .. catch construct and in catch block either log the exception or perform as necessary.
MySQL stored procedure will throw the error out if there is no rollback command for SQLEXCEPTION, but it has changed some data before the exception.
I add rollback command for SQL exceptions:
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
END;
But I can not know the reason of the rollback now.
I know we can define every SQL exception and it's handler, but it's too complex and I just want to know why the rollback occurred.
Is there a simple method to get the reason of rollback in MySQL stored procedure?
Thanks #kordirko. I have get one solution with RESIGNAL. But it is only supported until MySQL 5.5.
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
SET #flag = 1;
IF #flag = 1 THEN RESIGNAL;END IF;
ROLLBACK;
END;
I have been trying to catch mysql exception especially for triggers and store procedures.How can we catch the exception from mysql side?. I still not found any solution. your help would be appreciate.
Thanks
Hitesh
Because this comes up in the top of my search for MySQL error handling in triggers, I thought I'd share my solution for MySQL 5.5+
My original post: https://stackoverflow.com/a/26115231/1733365 Duplicated below...
Because this article comes up towards the top when I search for error handling in MySQL triggers, I thought I'd share some knowledge.
If there is an error, you can force MySQL to use a SIGNAL, but if you don't specify it as a class as SQLEXCEPTION, then nothing will happen, as not all SQLSTATEs are considered bad, and even then you'd have to make sure to RESIGNAL if you have any nested BEGIN/END blocks.
Alternatively, and probably simpler still, within your trigger, declare an exit handler and resignal the exception.
CREATE TRIGGER `my_table_AINS` AFTER INSERT ON `my_table` FOR EACH ROW
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
RESIGNAL;
DECLARE EXIT HANDLER FOR SQLWARNING
RESIGNAL;
DECLARE EXIT HANDLER FOR NOT FOUND
RESIGNAL;
-- Do the work of the trigger.
END
And if in your body there occurs an error, it will be thrown back up to the top and exit with an error. This can also be used in stored procedures and whatnot.
This works with anything version 5.5+.
Check out the syntax for DECLARE HANDLER
http://dev.mysql.com/doc/refman/5.1/en/declare-handler.html
Also, if you're trying to debug a SP, this might be helpful for you:
http://www.bluegecko.net/mysql/debugging-stored-procedures/