web-dev-qa-db-fra.com

transaction mysql - annuler toute exception

Est-il possible de revenir en arrière automatiquement en cas d'erreur sur une liste de commandes mysql?

par exemple quelque chose comme:

begin transaction;

insert into myTable values1 ...
insert into myTable values2 ...;  -- will throw an error

commit;

maintenant, lors de l'exécution, je veux que toute la transaction échoue, et donc je devrais PAS voir values1 dans myTable. mais malheureusement, la table est pupulée avec des valeurs1 même si la transaction comporte des erreurs.

des idées sur la façon de le faire revenir en arrière? (encore une fois, en cas d'erreur)?

EDIT - changé de DDL à SQL standard

29
Urbanleg

Vous pouvez utiliser 13.6.7.2. DECLARE ... HANDLER Syntax de la manière suivante:

DELIMITER $$

CREATE PROCEDURE `sp_fail`()
BEGIN
    DECLARE `_rollback` BOOL DEFAULT 0;
    DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET `_rollback` = 1;
    START TRANSACTION;
    INSERT INTO `tablea` (`date`) VALUES (NOW());
    INSERT INTO `tableb` (`date`) VALUES (NOW());
    INSERT INTO `tablec` (`date`) VALUES (NOW()); -- FAIL
    IF `_rollback` THEN
        ROLLBACK;
    ELSE
        COMMIT;
    END IF;
END$$

DELIMITER ;

Pour un exemple complet, vérifiez ce qui suit SQL Fiddle .

46
wchiquito

Vous pouvez utiliser EXIT HANDLER si vous avez par exemple besoin de SIGNALER une EXCEPTION SQL spécifique dans votre code. Par exemple:

DELIMITER $$

CREATE PROCEDURE `sp_fail`()
BEGIN
    DECLARE EXIT HANDLER FOR SQLEXCEPTION
    BEGIN
        ROLLBACK;  -- rollback any changes made in the transaction
        RESIGNAL;  -- raise again the sql exception to the caller
    END;

    START TRANSACTION;
    insert into myTable values1 ...
    IF fail_condition_meet THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Custom error detected.', MYSQL_ERRNO = 2000;
    END IF;
    insert into myTable values2 ...  -- this will not be executed
    COMMIT; -- this will not be executed
END$$

DELIMITER ;
21
KGs

La solution ci-dessus est bonne mais pour la rendre encore plus simple

DELIMITER $$

CREATE PROCEDURE `sp_fail`()
BEGIN
    DECLARE EXIT HANDLER FOR SQLEXCEPTION
    BEGIN
        ROLLBACK;  -- rollback any error in the transaction
    END;

    START TRANSACTION;
    insert into myTable values1 ...
    insert into myTable values2 ...  -- Fails
    COMMIT; -- this will not be executed
END$$

DELIMITER ;
0
James