You can use transaction in a procedure. *We cannot use transaction in a function.
For example, you create test
table as shown below:
CREATE TABLE test (
num int
);
Then, you insert the row whose num is 2
as shown below:
INSERT INTO test (num) VALUES (2);
Then, you create my_proc()
procedure which updates num
to 5
, then causes error by SIGNAL statement, then rollbacks with ROLLBACK statement in a transaction (START TRANSACTION and COMMIT statements) as shown below:
DELIMITER $$
CREATE PROCEDURE my_proc()
BEGIN
START TRANSACTION;
UPDATE test SET num = 5;
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'An error occurred';
ROLLBACK;
COMMIT;
END$$
DELIMITER ;
Then, calling my_proc()
gets the error but num
is not rollbacked to 2
as shown below:
mysql> CALL my_proc();
ERROR 1644 (45000): An error occurred
...
mysql> SELECT num FROM test;
+------+
| num |
+------+
| 5 |
+------+
Now, you can rollback the transaction in my_proc()
procedure with DECLARE ... HANDLER statement as shown below. *Be careful, my_proc()
procedure without a transaction (START TRANSACTION
and COMMIT
statements) doesn't rollback num
to 2
:
DELIMITER $$
CREATE PROCEDURE my_proc()
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
END;
START TRANSACTION;
UPDATE test SET num = 5;
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'An error occurred';
COMMIT;
END$$
DELIMITER ;
Or, you can rollback the transaction in my_proc()
procedure with this below:
DELIMITER $$
CREATE PROCEDURE my_proc()
BEGIN
DECLARE `_rollback` BOOL DEFAULT 0;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
SET `_rollback` = 1;
END;
START TRANSACTION;
UPDATE test SET num = 5;
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'An error occurred';
IF `_rollback` THEN
ROLLBACK;
ELSE
COMMIT;
END IF;
END$$
DELIMITER ;
Then, calling my_proc()
doesn't get error because the error is handled by DECLARE ... HANDLER
statement, then num
is rollbacked to 2
as shown below:
mysql> CALL my_proc();
...
mysql> SELECT num FROM test;
+------+
| num |
+------+
| 2 |
+------+