Как обнаружить откат в хранимой процедуре MySQL?
Я пытаюсь найти способ обнаружить возникновение отката в хранимой процедуре MySQL, чтобы я мог соответствующим образом справиться с ситуацией с помощью PHP-скрипта, но пока я не могу найти никакого решения.
Моя хранимая процедура выглядит следующим образом:
delimiter |
create procedure multi_inserts(
IN var1 int(11),
.
.
.
IN string1 text
)
BEGIN
declare exit handler for sqlexception rollback;
declare exit handler for sqlwarning rollback;
START TRANSACTION;
insert into table1(a,b,c,d) values(var1,var2,var3,var4);
insert into table2(e,f,g) values(var5,var6,string1);
COMMIT;
END
delimiter ;
Я провел тест отката для этой процедуры, и он откатился, но я не получил ложных результатов. Я хочу, чтобы моя хранимая процедура выдавала какое-то сообщение об ошибке, если транзакция не удалась, поэтому я мог бы обработать ее следующим образом это:
$result = mysql_query($procedure);
if(!$result)
{
//rollback occured do something
}
Есть ли способ обнаружить откат в MySQL? Я что-то упускаю? Любой ответ будет оценен по достоинству. Спасибо за чтение.
Благодаря вашим советам я исправил эту проблему. Вот что я сделал:
Хранимая процедура
delimiter |
create procedure multi_inserts(
IN var1 int(11),
.
.
.
IN string1 text
)
BEGIN
declare exit handler for sqlexception sqlwarning
BEGIN
rollback;
select -1;
END;
START TRANSACTION;
insert into table1(a,b,c,d) values(var1,var2,var3,var4);
insert into table2(e,f,g) values(var5,var6,string1);
COMMIT;
END
delimiter ;
Если я использую переменную out вместо select-1, это приводит к следующей ошибке:
Аргумент OUT или INOUT не является переменной или НОВОЙ псевдопеременной в ПЕРЕД запуском
Я не знаю, что я сделал неправильно, но я не мог решить эту проблему.
PHP-скрипт
$result=mysqli_query($con,$procedure);
if(is_object($result))
{
//rollback happened do something!
}
Если SP успешен, он выдает значение true.
4 answers
Вы можете добавить выходной параметр, а затем установить его в нужное значение в обработчиках выхода.
Вот пример использования вашей процедуры:
delimiter $$
create procedure multi_inserts(
IN var1 int(11),
.
.
.
IN string1 text,
OUT p_return_code tinyint unsigned
)
BEGIN
DECLARE exit handler for sqlexception
BEGIN
-- ERROR
set p_return_code = 1;
rollback;
END;
DECLARE exit handler for sqlwarning
BEGIN
-- WARNING
set p_return_code = 2;
rollback;
END;
START TRANSACTION;
insert into table1(a,b,c,d) values(var1,var2,var3,var4);
insert into table2(e,f,g) values(var5,var6,string1);
COMMIT;
-- SUCCESS
set p_return_code = 0;
END $$
delimiter ;
Обычно вы делали бы это на стороне PHP, если бы хотели отлавливать ошибки. Читать http://php.net/manual/en/pdo.transactions.php для получения дополнительной информации.
Эй, сделай одну вещь, используй ВЫХОДНУЮ переменную и возвращай 1 или 0 в качестве результата формы SP и делай все, что захочешь, с этим флагом.
<?php
try {
$user='root';
$pass='';
$dbh = new PDO('mysql:host=localhost;dbname=dbname', $user, $pass,
array(PDO::ATTR_PERSISTENT => true));
echo "Connected\n";
} catch (Exception $e) {
die("Unable to connect: " . $e->getMessage());
}
try {
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->beginTransaction();
$dbh->exec("insert into staff (id, first, last) values (23, 'Joe', 'Bloggs')");
$dbh->exec("insert into salarychange (id, amount, changedate)
values (23, 50000, NOW())");
$dbh->commit();
}
catch (Exception $e) {
$dbh->rollBack();
echo "Failed: " . $e->getMessage();
}
?>