【问题标题】:How can I see errors from a MySQL stored procedure?如何查看 MySQL 存储过程中的错误?
【发布时间】:2011-12-09 16:14:19
【问题描述】:

关于使用带有事务的 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 ;

【问题讨论】:

    标签: mysql perl stored-procedures dbi


    【解决方案1】:

    除了在退出处理程序中进行回滚之外,您还需要返回一些东西...

    你目前有

    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 ;
    

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

    【讨论】:

    • @NXT 您只是将“ret”用作真/假,而不是使用它来为自己提供所需的信息。 (如,更详细的故障信息)。我的回答向您展示了一种做您想做的事情的方法。我将使用您可能想要尝试的更多信息来编辑我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-08
    • 2023-03-23
    • 1970-01-01
    • 2010-12-30
    • 2019-07-08
    • 2015-09-22
    相关资源
    最近更新 更多