Как я могу увидеть ошибки хранимой процедуры MySQL? - PullRequest
0 голосов
/ 18 октября 2011

Что касается использования хранимых процедур 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 ;

1 Ответ

2 голосов
/ 18 октября 2011

Вместо того, чтобы просто выполнить откат в обработчике выхода, вам также нужно что-то вернуть ...

У вас сейчас есть

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 ;

Делая это таким образом, вы добавляете еще один параметр out, но он дает вам гораздо лучшую информацию. Вы можете сделать то же самое с несколькими обработчиками выхода.

...