关于将MySQL存储过程与事务一起使用,我在获取错误输出方面遇到了问题。
问题是我需要设置一个exit_handler来回滚事务,如果有什么失败的话。但是当我这样做时,如果出现问题,我不会得到任何错误输出。例如,如果我不小心传递了NULL值并尝试将其插入到非空字段中。
我使用返回值以编程方式指示成功或失败,但这并没有告诉我实际出错的地方。
我使用Perl DBI与MySQL交谈。我在生产服务器上使用MySQL 5.0.92,在开发服务器上使用MySQL 5.0.51a。升级到更新版本的MySQL在政治上是站不住脚的。
这是一个简化的例子:
DELIMITER //
CREATE PROCEDURE pmt_new(
app_id varchar(40),
out ret tinyint unsigned,
out pmt_req_id int(10) unsigned)
BEGIN
DECLARE v_pmt_req_type int(10) unsigned;
DECLARE exit handler for not found, sqlwarning, sqlexception rollback;
set ret=1;
START TRANSACTION;
SELECT pmt_type INTO v_pmt_req_type FROM pmt_req_types WHERE pmt_req_name = 'Name 1';
INSERT INTO pmt_reqs (pmt_req_id, pmt_req_type, app_id)
values (null, v_pmt_req_type, app_id);
set pmt_req_id = last_insert_id();
INSERT INTO other (pmt_req_id) values (pmt_req_id);
COMMIT;
set ret=0;
END//
DELIMITER ;
答案 0 :(得分:2)
您不仅要在退出处理程序中执行回滚,还需要返回一些内容......
你目前有
DECLARE exit handler for not found, sqlwarning, sqlexception rollback;
将其更改为......
DECLARE exit handler for not found, sqlwarning, sqlexception
begin
rollback;
select "We had to rollback, error!";
end;
在5.5中,他们添加了SIGNAL / RESIGNAL语句,因此您可以“返回”错误,但在以前的版本中,您必须推出自己的解决方案。如果需要,您可以声明多个退出处理程序以更好地定制输出,或者设置您可以从中提取的错误表。
您还可以在存储过程中进行输入测试。想知道app_id是否为空?
DELIMITER //
CREATE PROCEDURE pmt_new(
app_id varchar(40),
out result varchar(256),
out ret tinyint unsigned,
out pmt_req_id int(10) unsigned)
BEGIN
DECLARE v_pmt_req_type int(10) unsigned;
DECLARE exit handler for not found, sqlwarning, sqlexception rollback;
SET ret=1;
SET result = "";
IF app_id IS NULL THEN
set result = "Supplied ID is Null";
ELSE
START TRANSACTION;
SELECT pmt_type INTO v_pmt_req_type FROM pmt_req_types WHERE pmt_req_name = 'Name 1';
INSERT INTO pmt_reqs (pmt_req_id, pmt_req_type, app_id)
values (null, v_pmt_req_type, app_id);
set pmt_req_id = last_insert_id();
INSERT INTO other (pmt_req_id) values (pmt_req_id);
COMMIT;
set ret=0;
END IF;
END//
DELIMITER ;
这样做会添加另一个输出参数,但会为您提供更好的信息。您可以使用多个退出处理程序执行相同操作。