MySQL PL/SQL Errors / Exceptions support

Functions like mysql_error() in PHP or try/catch blocks and MySqlException in C# are very helpful to discover problems.
Unfortunately, inside stored procedure (routine) there is no ready component to catch errors to see what would return SHOW ERRORS. But I have wanted such feature at my EVENT (Event Scheduler)! Hopefully, I realized that I can divide my code into many blocks with separate blocks responsible for error handling and thus collect these bad queries (then inspect’em all).
That can be represented in such manner:

BEGIN
 DECLARE EXIT|CONTINUE HANDLER FOR SQLEXCEPTION;
  BEGIN
   DO SOMETHING ON ERROR;
  END
 DO STH;
 BEGIN
  DECLARE EXIT|CONTINUE HANDLER FOR SQLEXCEPTION;
   BEGIN
    DO SOMETHING ON ERROR2;
   END
  DO SOMETHING ELSE;
 END
END

Example:

1. Create tables.

CREATE TABLE IF NOT EXISTS `routine_error` (
  `id` int(10) unsigned NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Test table';


CREATE TABLE IF NOT EXISTS `routine_logs` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `error_sql` text,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Test table' AUTO_INCREMENT=1 ;


2. Create procedure.

CREATE PROCEDURE `RoutineErrorTest` ()
MAIN_BLOCK: BEGIN
DECLARE MyId INT(11) UNSIGNED DEFAULT 0;
DECLARE done TINYINT DEFAULT 0;
DECLARE MyCursor CURSOR FOR Select `Id` From  `routine_error`;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
  
SET done = 0;
OPEN MyCursor;
REPEAT  	
 IF done = 0 THEN
  UNIQUE_JOIN_BLOCK: BEGIN
   DECLARE EXIT HANDLER FOR SQLEXCEPTION
    BEGIN 
     -- Make clear (Rollback, etc)
     /* Log. This works provided that the bug is not in this query :) */
     INSERT INTO `routine_logs` (`id`, `error_sql`) VALUES (NULL, @InsertSQL);
    END;			
   FETCH MyCursor INTO MyId;
   SET @InsertSQL = CONCAT("INSERT INTO routine_error (`id`) VALUES(", MyId, ");");
   PREPARE MyStmt FROM @InsertSQL;
   EXECUTE MyStmt;
  END UNIQUE_JOIN_BLOCK;
 END IF;
UNTIL done END REPEAT;
CLOSE MyCursor;
END MAIN_BLOCK;

Voila, your errors are here:

SELECT * FROM routine_logs;
  1. No comments yet.

  1. No trackbacks yet.