如何查看 MySQL 存储过程中的错误?

发布于 2024-12-11 00:46:30 字数 997 浏览 0 评论 0原文

关于将 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 ;

With regards to using MySQL stored procedures with transactions, and I am having a problem getting error output.

The problem is that I need to set an exit_handler to roll back the transaction if anything fails. But when I do this, I don't get any error output if something goes wrong. For example if I accidentally pass a NULL value and try to insert it into a non-null field.

I am using a return value to programmatically indicate success or failure, however this does nothing to tell me what actually went wrong.

I am using Perl DBI to talk to MySQL. I am using MySQL 5.0.92 on the production server and MySQL 5.0.51a on the development server. Upgrading to a newer version of MySQL is politically untenable.

This is a simplified example:

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 ;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

锦爱 2024-12-18 00:46:30

您不仅需要在退出处理程序中进行回滚,还需要返回一些内容...

您当前已将

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 ;

这样做会添加另一个输出参数,但会为您提供更好的信息。您可以对多个退出处理程序执行相同的操作。

Instead of just doing a rollback in your exit handler you need to return something as well...

You currently have

DECLARE exit handler for not found, sqlwarning, sqlexception rollback;

Change it to something like...

DECLARE exit handler for not found, sqlwarning, sqlexception
  begin
    rollback;
    select "We had to rollback, error!";
  end;

In 5.5 they added the SIGNAL/RESIGNAL statements so you could 'return' an error but prior versions you have to kind of roll your own solution. If you need you can declare multiple exit handlers to tailor the output better, or setup your own error table you can pull from.

You can also do input testing inside your stored procedure. Want to know if app_id is null?

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 ;

Doing it this way adds another out parameter, but gives you much better information. You could do the same with multiple exit handlers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文