mysql Transaction in the commit block - mysql

CREATE DEFINER=`root`#`localhost` PROCEDURE `PrcCopyQuestion_Admin`(in Param1,in Param2 varchar(45))
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
Select 'Fail' as 'Status' ;
END;
DECLARE EXIT HANDLER FOR sqlwarning
BEGIN
ROLLBACK;
Select 'Fail' as 'Status' ;
END;
Start transaction;
Insert statement 1;
Insert statement 2;
SELECT 'Success' AS 'Status';
call PrcGetQuestionAndOption_Admin(#variable);
Commit;
END
I am using Mysql 5.7. When in the commit block if the second (Insert statement 2) fails. It will go in the Rollback part and gives me output as 'Failed'. But when i am getting the output it still executes the Select 'Success' as Status in commit block.
So my question is when the second insert statement fails. It should go directly in rollback and give me status as fail. It should not execute the status as 'success' in commit block.
Eg: On rollback I am getting two result set:
Select 'Fail'..1st result set
Select 'Success'....2nd result set
I need output as only
Select 'fail'
Any help appreciated!!

I can't reproduce the problem.
mysql> SELECT VERSION();
+-----------+
| VERSION() |
+-----------+
| 5.7.12 |
+-----------+
1 row in set (0.00 sec)
mysql> DROP TABLE IF EXISTS `t1`, `t2`;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE IF NOT EXISTS `t1` (
-> `c0` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE IF NOT EXISTS `t2` (
-> `c0` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> DELIMITER //
mysql> DROP PROCEDURE IF EXISTS `PrcCopyQuestion_Admin`//
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE PROCEDURE `PrcCopyQuestion_Admin`(Param1 INT, Param2 VARCHAR(45))
-> BEGIN
-> DECLARE EXIT HANDLER FOR SQLEXCEPTION
-> BEGIN
-> ROLLBACK;
-> SELECT 'Fail' Status;
-> END;
-> DECLARE EXIT HANDLER FOR SQLWARNING
-> BEGIN
-> ROLLBACK;
-> SELECT 'Fail' Status;
-> END;
-> START TRANSACTION;
-> INSERT INTO `t1` (`c0`) VALUES (0);
-> IF Param1 = 0 THEN
-> INSERT INTO `ERR_t2` (`c0`) VALUES (0);
-> ELSE
-> INSERT INTO `t2` (`c0`) VALUES (0);
-> END IF;
-> SELECT 'Success' Status;
-> COMMIT;
-> END//
Query OK, 0 rows affected (0.00 sec)
mysql> DELIMITER ;
mysql> CALL `PrcCopyQuestion_Admin`(0, NULL);
+--------+
| Status |
+--------+
| Fail |
+--------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT
-> `c0`
-> FROM
-> `t1`;
Empty set (0.00 sec)
mysql> SELECT
-> `c0`
-> FROM
-> `t2`;
Empty set (0.00 sec)
mysql> CALL `PrcCopyQuestion_Admin`(1, NULL);
+---------+
| Status |
+---------+
| Success |
+---------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT
-> `c0`
-> FROM
-> `t1`;
+----+
| c0 |
+----+
| 2 |
+----+
1 row in set (0.00 sec)
mysql> SELECT
-> `c0`
-> FROM
-> `t2`;
+----+
| c0 |
+----+
| 1 |
+----+
1 row in set (0.00 sec)

Related

Trigger to create varchar auto increment with if else statement

Hi Does anybody know how I should create a trigger that will create a unique id from varchar and auto increment table including if else from user input
I was planning something similar to the below code but i am getting an error 1050 table user_increment_table exist
DELIMITER ;
CREATE TRIGGER TG_ID
BEFORE INSERT ON userdatabase
FOR EACH ROW
BEGIN
if User_department like "HR"
then
INSERT INTO user_increment_table VALUES (NULL);
SET NEW.User_ID = CONCAT('HRU', LPAD(LAST_INSERT_ID(), 3, '0'));
Elseif U_role like "MARKETING"
then
INSERT INTO user_increment_table VALUES (NULL);
SET NEW.User_ID = CONCAT('MRK', LPAD(LAST_INSERT_ID(), 3, '0'));
END$$
DELIMITER ;
Try:
mysql> DROP TABLE IF EXISTS `user_increment_table`, `userdatabase`;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE IF NOT EXISTS `userdatabase` (
-> `User_ID` VARCHAR(6),
-> `User_department` VARCHAR(255),
-> `U_role` VARCHAR(255)
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE IF NOT EXISTS `user_increment_table` (
-> `id` BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> DELIMITER //
mysql> CREATE TRIGGER `TG_ID` BEFORE INSERT ON `userdatabase`
-> FOR EACH ROW
-> BEGIN
-> IF NEW.`User_department` LIKE 'HR' THEN
-> INSERT INTO `user_increment_table` VALUES (NULL);
-> SET NEW.`User_ID` := CONCAT('HRU', LPAD(LAST_INSERT_ID(), 3, '0'));
-> ELSEIF NEW.`U_role` LIKE 'MARKETING' THEN
-> INSERT INTO user_increment_table VALUES (NULL);
-> SET NEW.`User_ID` := CONCAT('MRK', LPAD(LAST_INSERT_ID(), 3, '0'));
-> END IF;
-> END//
Query OK, 0 rows affected (0.00 sec)
mysql> DELIMITER ;
mysql> INSERT INTO `userdatabase` (`User_department`)
-> VALUES ('HR');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO `userdatabase` (`U_role`)
-> VALUES ('MARKETING');
Query OK, 1 row affected (0.00 sec)
mysql> SELECT
-> `User_ID`,
-> `User_department`,
-> `U_role`
-> FROM
-> `userdatabase`;
+---------+-----------------+-----------+
| User_ID | User_department | U_role |
+---------+-----------------+-----------+
| HRU001 | HR | NULL |
| MRK002 | NULL | MARKETING |
+---------+-----------------+-----------+
2 rows in set (0.00 sec)
See db-fiddle.

Stored procedure SQLWARNING exit handler not invoked

(First post. Apologize if I breach any customs or protocol.)
I want to define an exit handler for any SQLWARNING thrown in my stored procedure. But the handler is being ignored, it never fires. And I am very confused.
I am using MariaDB v. 10.0.23. However I have tested this on MariaDB v. 10.1.14 and get the same result.
Below is the SQL to create a test database.
CREATE DATABASE testerrorhandling;
USE testerrorhandling;
CREATE TABLE test
(
int_notnull INT NOT NULL
);
DELIMITER //
CREATE DEFINER=CURRENT_USER PROCEDURE create_record
(
IN p INT
)
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
SELECT 'Handler for SQLEXCEPTION fired.';
DECLARE EXIT HANDLER FOR SQLWARNING
SELECT 'Handler for SQLWARNING fired.';
INSERT INTO test (int_notnull) VALUES (p);
END;
//
DELIMITER ;
If I attempt to add a null value, the procedure invokes the correct handler.
MariaDB [testerrorhandling]> call create_record(null);
+---------------------------------+
| Handler for SQLEXCEPTION fired. |
+---------------------------------+
| Handler for SQLEXCEPTION fired. |
+---------------------------------+
1 row in set (0.00 sec)
But now if I attempt to add a non-integer value, a warning is thrown but the SQLWARNING error handler never fires. A value of 0 is stored in the test table.
MariaDB [testerrorhandling]> call create_record('this is not an integer');
Query OK, 1 row affected, 1 warning (0.04 sec)
MariaDB [testerrorhandling]> show warnings;
+---------+------+---------------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------------------------------------------+
| Warning | 1366 | Incorrect integer value: 'this is not an integer' for column 'p' at row 1 |
+---------+------+---------------------------------------------------------------------------+
1 row in set (0.00 sec)
This is not what I expect or desire. I have to be doing something wrong. What am I missing here?
The warning occurs in the stored procedure call, not within the stored procedure, so the warning (within stored procedure) is not fired.
In the following example you can see that the parameter p has a value of zero (0) within the stored procedure, so there is no warning:
MariaDB [_]> DROP TABLE IF EXISTS test;
Query OK, 0 rows affected (0.00 sec)
MariaDB [_]> DROP PROCEDURE IF EXISTS create_record;
Query OK, 0 rows affected (0.00 sec)
MariaDB [_]> CREATE TABLE IF NOT EXISTS test (
-> int_notnull INT NOT NULL
-> );
Query OK, 0 rows affected (0.00 sec)
MariaDB [_]> DELIMITER //
MariaDB [_]> CREATE PROCEDURE create_record (
-> IN p INT
-> )
-> BEGIN
-> DECLARE EXIT HANDLER FOR SQLEXCEPTION
-> SELECT 'Handler for SQLEXCEPTION fired.';
->
-> DECLARE EXIT HANDLER FOR SQLWARNING
-> SELECT 'Handler for SQLWARNING fired.';
->
-> SELECT CONCAT('VALUE OF p: ', p);
-> INSERT INTO test (int_notnull) VALUES (p);
-> END//
Query OK, 0 rows affected (0.00 sec)
MariaDB [_]> DELIMITER ;
MariaDB [_]> call create_record('this is not an integer');
+---------------------------+
| CONCAT('VALUE OF p: ', p) |
+---------------------------+
| VALUE OF p: 0 |
+---------------------------+
1 row in set (0.00 sec)
Query OK, 1 row affected, 1 warning (0.00 sec)
MariaDB [_]> SHOW WARNINGS;
+---------+------+---------------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------------------------------------------+
| Warning | 1366 | Incorrect integer value: 'this is not an integer' for column 'p' at row 1 |
+---------+------+---------------------------------------------------------------------------+
1 row in set (0.00 sec)
In the following example, the warning is fired in the call to and within the stored procedure:
MariaDB [_]> DROP TABLE IF EXISTS test;
Query OK, 0 rows affected (0.00 sec)
MariaDB [_]> DROP PROCEDURE IF EXISTS create_record;
Query OK, 0 rows affected (0.00 sec)
MariaDB [_]> CREATE TABLE IF NOT EXISTS test (
-> int_notnull INT NOT NULL
-> );
Query OK, 0 rows affected (0.00 sec)
MariaDB [_]> DELIMITER //
MariaDB [_]> CREATE PROCEDURE create_record (
-> IN p INT
-> )
-> BEGIN
-> DECLARE EXIT HANDLER FOR SQLEXCEPTION
-> SELECT 'Handler for SQLEXCEPTION fired.';
->
-> DECLARE EXIT HANDLER FOR SQLWARNING
-> SELECT 'Handler for SQLWARNING fired.';
->
-> SELECT CONCAT('VALUE OF p: ', p);
-> SET p := 'this is not an integer';
-> INSERT INTO test (int_notnull) VALUES (p);
-> END//
Query OK, 0 rows affected (0.00 sec)
MariaDB [_]> DELIMITER ;
MariaDB [_]> call create_record('this is not an integer');
+---------------------------+
| CONCAT('VALUE OF p: ', p) |
+---------------------------+
| VALUE OF p: 0 |
+---------------------------+
1 row in set (0.00 sec)
+-------------------------------+
| Handler for SQLWARNING fired. |
+-------------------------------+
| Handler for SQLWARNING fired. |
+-------------------------------+
1 row in set (0.00 sec)
Query OK, 0 rows affected, 1 warning (0.00 sec)
MariaDB [_]> SHOW WARNINGS;
+---------+------+---------------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------------------------------------------+
| Warning | 1366 | Incorrect integer value: 'this is not an integer' for column 'p' at row 1 |
+---------+------+---------------------------------------------------------------------------+
1 row in set (0.00 sec)

Unable to use SIGNAL and INSERT at the same time

I have a problem with this trigger. When I use the INSERT and the SIGNAL statements inside the IF condition, the insertion is not performed. However, without SIGNAL, the insertion is done. Anyone have an explanation for that? My main concern is that I need both the insertion and the SIGNAL statement to cancel the main insertion (the insertion that throws the trigger)
DELIMITER //
CREATE TRIGGER log_venta BEFORE INSERT ON `venta_producto`
FOR EACH ROW BEGIN
DECLARE value int;
DECLARE valor_venta int;
DECLARE saldo_cliente int;
DECLARE cliente_id int;
SELECT cliente INTO cliente_id FROM venta WHERE id=NEW.ventaID;
SELECT credito INTO saldo_cliente FROM cliente WHERE no_cliente=cliente_id;
SELECT precio INTO valor_producto FROM producto WHERE id=NEW.producto;
SET valor_venta = NEW.cantidad*valor_producto;
IF valor_venta > saldo_cliente THEN
INSERT INTO log(cliente) VALUES (cliente_id);
SIGNAL SQLSTATE '02000' SET MESSAGE_TEXT = 'ERROR';
END IF;
END
//
DELIMITER ;
Thanks
14.6.7.5 SIGNAL Syntax
. . .
SIGNAL is the
way to “return” an error.
. . .
21.3.1 Trigger Syntax and Examples
. . .
For transactional tables, failure of a statement should cause rollback of all changes performed by the statement. Failure of a
trigger causes the statement to fail, so trigger failure also causes
rollback. For nontransactional tables, such rollback cannot be done,
so although the statement fails, any changes performed prior to the
point of the error remain in effect.
. . .
Mentioned above can be demonstrated in the following example:
mysql> DROP TABLE IF EXISTS `venta_producto`;
Query OK, 0 rows affected (0.00 sec)
mysql> DROP TABLE IF EXISTS `log`;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE IF NOT EXISTS `venta_producto` (
-> `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
-> `cliente_id` INT UNSIGNED
-> );
Query OK, 0 rows affected (0.01 sec)
mysql> CREATE TABLE IF NOT EXISTS `log` (
-> `cliente_id` INT UNSIGNED
-> ) ENGINE=InnoDB;
Query OK, 0 rows affected (0.00 sec)
mysql> DELIMITER //
mysql> CREATE TRIGGER `log_venta` BEFORE INSERT ON `venta_producto`
-> FOR EACH ROW
-> BEGIN
-> INSERT INTO `log` (`cliente_id`) VALUES (NEW.`cliente_id`);
-> SIGNAL SQLSTATE '02000' SET MESSAGE_TEXT = 'ERROR';
-> END//
Query OK, 0 rows affected (0.00 sec)
mysql> DELIMITER ;
mysql> INSERT INTO `venta_producto`
-> (`cliente_id`)
-> VALUES
-> (1);
ERROR 1643 (02000): ERROR
mysql> SELECT
-> `id`,
-> `cliente_id`
-> FROM
-> `venta_producto`;
Empty set (0.00 sec)
mysql> SELECT
-> `cliente_id`
-> FROM
-> `log`;
Empty set (0.00 sec)
mysql> ALTER TABLE `log` ENGINE=MyISAM;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> INSERT INTO `venta_producto`
-> (`cliente_id`)
-> VALUES
-> (2);
ERROR 1643 (02000): ERROR
mysql> SELECT
-> `id`,
-> `cliente_id`
-> FROM
-> `venta_producto`;
Empty set (0.00 sec)
mysql> SELECT
-> `cliente_id`
-> FROM
-> `log`;
+------------+
| cliente_id |
+------------+
| 2 |
+------------+
1 row in set (0.00 sec)

setting variable in case of exception

I have a stored procedure which will set my customized error as well as set an out variable to some value . I tried the following procedure .
***delimiter //
drop procedure if exists test_dalpu //
create procedure test_dalpu(out out_value int)
begin
DECLARE EXIT HANDLER FOR SQLSTATE '22001'
BEGIN
set out_value = 1;
SIGNAL SQLSTATE '22001' SET
MYSQL_ERRNO = 2,
MESSAGE_TEXT = 'Too long ';
END;
insert into abc_test values ( 5,"eerrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr");***
end//
delimiter ;
Then after executing
**call test_dalpu(#out_value);**
I got the correct output as Error code 2 Too long as expected, But after that If I do
select #out_value;
Am getting the value as null instead of 1 .
Is it the correct way?
Try:
mysql> DROP PROCEDURE IF EXISTS `test_dalpu`;
Query OK, 0 rows affected (0.00 sec)
mysql> DROP TABLE IF EXISTS `abc_test`;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE IF NOT EXISTS `abc_test` (
-> `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
-> `description` CHAR(10)
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> DELIMITER //
mysql> CREATE PROCEDURE `test_dalpu`(`out_value` VARCHAR(64))
-> BEGIN
-> DECLARE EXIT HANDLER FOR SQLSTATE '22001'
-> BEGIN
-> ROLLBACK;
-> SET #`set_variable` := CONCAT('SET #`', `out_value`, '` := 1');
-> PREPARE `stmt` FROM #`set_variable`;
-> EXECUTE `stmt`;
-> DEALLOCATE PREPARE `stmt`;
-> SIGNAL SQLSTATE '22001' SET
-> MYSQL_ERRNO = 2,
-> MESSAGE_TEXT = 'Too long';
-> END;
-> START TRANSACTION;
-> INSERT INTO `abc_test`
-> (`description`)
-> VALUES
-> ('ABCDEFGHIJK');
-> COMMIT;
-> END//
Query OK, 0 rows affected (0.00 sec)
mysql> DELIMITER ;
mysql> SET #`out_value` := NULL;
Query OK, 0 rows affected (0.00 sec)
mysql> CALL `test_dalpu`('out_value');
ERROR 2 (22001): Too long
mysql> SHOW WARNINGS;
+-------+------+----------+
| Level | Code | Message |
+-------+------+----------+
| Error | 2 | Too long |
+-------+------+----------+
1 row in set (0.00 sec)
mysql> SELECT #`out_value`;
+--------------+
| #`out_value` |
+--------------+
| 1 |
+--------------+
1 row in set (0.00 sec)

Prepared statement needs to be re-prepared in mysql

I'm trying to access data from view and insert into a temptable, inside a store procedure, below is the store procedure .
When I try to execute the sp I'm getting "Prepared statement needs to be re-prepared" error.
Can some one pls suggest how to fix this error in mysql.
Procedure:
DROP PROCEDURE IF EXISTS getFilteredData;
CREATE PROCEDURE getFilteredData()
BEGIN
DECLARE sql2 VARCHAR(5000);
DROP TEMPORARY TABLE IF EXISTS TempTbl;
CREATE TEMPORARY TABLE TempTbl
(
ID VARCHAR(50),
Name VARCHAR(500),
Status INT
);
SET sql2 = 'INSERT INTO TempTbl Select ID,Name,Id as Status from v_release;';
SET #SWV_Stmt = sql2;
PREPARE SWT_Stmt FROM #SWV_Stmt;
EXECUTE SWT_Stmt;
DEALLOCATE PREPARE SWT_Stmt;
SELECT * FROM TempTbl;
END;
I can't reproduce the problem that you report.
mysql> SELECT VERSION();
+-----------------+
| VERSION() |
+-----------------+
| 5.5.22-0ubuntu1 |
+-----------------+
1 row in set (0.00 sec)
mysql> DELIMITER //
mysql> DROP TABLE IF EXISTS `release`//
Query OK, 0 rows affected (0.00 sec)
mysql> DROP VIEW IF EXISTS `v_release`//
Query OK, 0 rows affected (0.00 sec)
mysql> DROP PROCEDURE IF EXISTS `getFilteredData`//
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE `release` (
-> `id` VARCHAR(50),
-> `name` VARCHAR(500),
-> `status` INT
-> )//
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE VIEW `v_release` AS
-> SELECT `id`, `name`, `status`
-> FROM `release`//
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO `release`
-> (`id`, `name`, `status`)
-> VALUES
-> ('1', 'NAME1', 1),
-> ('2', 'NAME2', 2),
-> ('3', 'NAME1', 3)//
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> CREATE PROCEDURE `getFilteredData`()
-> BEGIN
-> DROP TEMPORARY TABLE IF EXISTS `temptbl`;
-> CREATE TEMPORARY TABLE `temptbl` (
-> `id` VARCHAR(50),
-> `name` VARCHAR(500),
-> `status` INT);
-> PREPARE `stmt` FROM 'INSERT INTO `temptbl`
'> SELECT `id`, `name`, `status`
'> FROM `v_release`';
-> EXECUTE `stmt`;
-> DEALLOCATE PREPARE `stmt`;
-> SELECT `id`, `name`, `status`
-> FROM `temptbl`;
-> DROP TEMPORARY TABLE IF EXISTS `temptbl`;
-> END//
Query OK, 0 rows affected (0.00 sec)
mysql> DELIMITER ;
mysql> CALL `getFilteredData`;
+------+-------+--------+
| id | name | status |
+------+-------+--------+
| 1 | NAME1 | 1 |
| 2 | NAME2 | 2 |
| 3 | NAME1 | 3 |
+------+-------+--------+
3 rows in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
SQL Fiddle demo