mysqlmysql5

Getting MySQL error creating handler in an event


I'm trying to create an Event in MySQL 5.6 and I'm getting an error whenever I try to DECLARE something, like a parameter or handler:

SQL Error [1064] [42000]: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET @rollMeBack = TRUE;

I'm a SQL Server guy and the syntax is giving me ulcers. I tried declaring a variable like in this question, but I still get the error at that line. Help me Obi Wan Kenobi: you're my only hope.

Entire (obfuscated) code:

DELIMITER ||

CREATE EVENT my_event
ON SCHEDULE EVERY 5 MINUTE
ON COMPLETION PRESERVE
ENABLE
COMMENT 'Fixes status'
DO IF EXISTS (
        SELECT NULL FROM [...problem records..]
    ) THEN
        -- =================================================================================================
        -- Get a complete list of bad records:
    SET @rollMeBack = FALSE ;

        SET @LogId = 0;
        CREATE TEMPORARY TABLE updateable
            SELECT DISTINCT e.id , (@LogId:=@LogId + 1) + (SELECT MAX(dsd.id) FROM LogTable dsd ) AS LogId
            FROM Table1 e 
                INNER JOIN Table2 r
                    ON r.e_id = e.id 
                    /*Waiting 5 minutes to not interfere with current operations:*/
                    AND r.rDateTime <= CURRENT_TIMESTAMP() - INTERVAL 5 MINUTE
            WHERE e.Status = 'Sent'
                AND NOT EXISTS(SELECT NULL FROM Table2 r2 WHERE r2.e_id = e.id and r2.rDateTime is null)
            LIMIT 100 ;
        
        -- =================================================================================================
        -- =================================================================================================
        DECLARE CONTINUE HANDLER FOR SQLEXCEPTION 
            SET @rollMeBack = TRUE;

        START TRANSACTION
            -- =================================================================================================
            UPDATE Table1 as e1 
                INNER JOIN updateable AS u
                    ON e1.d=id = u.id
            SET e1.Status = 'Completed',
                e1.cDateTime = COALESCE (e1.cDateTime, (select max(rDateTime) from Table2 r5 where r5.e_id = e1.id));
            -- =================================================================================================
            -- Log updates:
            INSERT INTO Debug (ID, Message)
            SELECT u.LogId,
                'Record set to `Completed`'
            FROM updateable AS u;
            -- =================================================================================================
            -- Cleanup:
            DROP TABLE updateable;

        IF @rollMeBack = TRUE THEN
            ROLLBACK;
        ELSE
            COMMIT;
        END IF
        -- =================================================================================================
        -- =================================================================================================
    END IF; ||

DELIMITER ;


Solution

  • A couple of modifications render this operable.

    Firstly, the handler must be declared in the correct place. From the docs:

    Handler declarations must appear after variable or condition declarations.

    Secondly, the DO IF EXISTS...END IF; should contain a BEGIN...END block after which you do your handler declaration:

    ...
    COMMENT 'Fixes status'
    DO IF EXISTS (
            SELECT NULL FROM [...problem records..]
        ) THEN
        BEGIN -- Note the added begin
            -- Moved the handler declaration to be the first statement of this block
            DECLARE CONTINUE HANDLER FOR SQLEXCEPTION 
                SET @rollMeBack = TRUE;
    
            -- =================================================================================================
            -- Get a complete list of bad records:
        SET @rollMeBack = FALSE ;
        ...
    

    At the end of the code:

            ...
            -- =================================================================================================
        END; -- Note the added END
    END IF; ||
    
    DELIMITER ;
    

    Incidentally, there is also a syntax error in the IF @rollMeBack = TRUE THEN...END IF block - the semi-colon is missing from the end of END IF.