Description:
Table Layout:
create table
mysum(
id int not null auto_increment primary key,
acc int,
amount decimal(10,2),
index (acc)
)
engine=INNODB;
create table
mytr(
id int not null auto_increment primary key,
acc int,
amount decimal(10,2),
status enum('I','P') not null,
index (acc),
FOREIGN KEY (acc) REFERENCES mysum (acc)
ON DELETE RESTRICT ON UPDATE CASCADE
)
engine=INNODB;
When I first tried to create procedure update_mytr like this:
_________________________________________________
delimiter &
CREATE PROCEDURE update_mytr()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE am decimal(10,2);
DECLARE ac,myid int;
DECLARE cur1 CURSOR FOR SELECT id,acc,amount FROM mytest.mytr where status='I';
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
OPEN cur1;
REPEAT
FETCH cur1 INTO myid, ac, am;
IF NOT done THEN
update mytest.mysum set amount=amount+am where acc=ac;
ELSE
update mytest.mytr set status='P' where status='I';
END IF;
UNTIL done END REPEAT;
CLOSE cur1;
END
&
_____________________________________________________
ERROR 1418 (HY000): This routine is declared to be non-deterministic and to
modify data and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)
change to deterministic helped:
_______________________________________________
delimiter &
CREATE PROCEDURE update_mytr() deterministic
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE am decimal(10,2);
DECLARE ac,myid int;
DECLARE cur1 CURSOR FOR SELECT id,acc,amount FROM mytest.mytr where status='I';
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
OPEN cur1;
REPEAT
FETCH cur1 INTO myid, ac, am;
IF NOT done THEN
update mytest.mysum set amount=amount+am where acc=ac;
ELSE
update mytest.mytr set status='P' where status='I';
END IF;
UNTIL done END REPEAT;
CLOSE cur1;
END
&
delimiter ;
________________________________________________________________
but if i run this procedure I get ERROR 2013:
tables befor call update_mytr()
mysql> select * from mytr;
+----+------+--------+--------+
| id | acc | amount | status |
+----+------+--------+--------+
| 1 | 300 | 10.00 | I |
| 2 | 400 | 10.00 | I |
| 3 | 400 | 10.00 | I |
| 4 | 400 | 14.00 | I |
+----+------+--------+--------+
4 rows in set (0.00 sec)
mysql> select * from mysum;
+----+------+--------+
| id | acc | amount |
+----+------+--------+
| 1 | 300 | 0.00 |
| 2 | 400 | 0.00 |
+----+------+--------+
2 rows in set (0.00 sec)
mysql> call update_mytr();
ERROR 2013 (HY000): Lost connection to MySQL server during query
tables after call update_mytr()
mysql> select * from mysum;
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id: 1
Current database: mytest
+----+------+--------+
| id | acc | amount |
+----+------+--------+
| 1 | 300 | 10.00 |
| 2 | 400 | 0.00 |
+----+------+--------+
2 rows in set (0.00 sec)
mysql> select * from mytr;
+----+------+--------+--------+
| id | acc | amount | status |
+----+------+--------+--------+
| 1 | 300 | 10.00 | I |
| 2 | 400 | 10.00 | I |
| 3 | 400 | 10.00 | I |
| 4 | 400 | 14.00 | I |
+----+------+--------+--------+
4 rows in set (0.00 sec)
How to repeat:
create table
mysum(
id int not null auto_increment primary key,
acc int,
amount decimal(10,2),
index (acc)
)
engine=INNODB;
create table
mytr(
id int not null auto_increment primary key,
acc int,
amount decimal(10,2),
status enum('I','P') not null,
index (acc),
FOREIGN KEY (acc) REFERENCES mysum (acc)
ON DELETE RESTRICT ON UPDATE CASCADE
)
engine=INNODB;
delimiter &
CREATE PROCEDURE update_mytr() deterministic # without ERROR 1418
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE am decimal(10,2);
DECLARE ac,myid int;
DECLARE cur1 CURSOR FOR SELECT id,acc,amount FROM mytest.mytr where status='I';
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
OPEN cur1;
REPEAT
FETCH cur1 INTO myid, ac, am;
IF NOT done THEN
update mytest.mysum set amount=amount+am where acc=ac;
ELSE
update mytest.mytr set status='P' where status='I';
END IF;
UNTIL done END REPEAT;
CLOSE cur1;
END
&
delimiter ;
mysql> select * from mysum;
+----+------+--------+
| id | acc | amount |
+----+------+--------+
| 1 | 300 | 0.00 |
| 2 | 400 | 0.00 |
+----+------+--------+
2 rows in set (0.00 sec)
mysql> select * from mytr;
+----+------+--------+--------+
| id | acc | amount | status |
+----+------+--------+--------+
| 1 | 300 | 10.00 | I |
| 2 | 400 | 10.00 | I |
| 3 | 400 | 10.00 | I |
| 4 | 400 | 14.00 | I |
+----+------+--------+--------+
4 rows in set (0.00 sec)
call update_mytr();