Question

En nettoyant cette réponse J'ai appris un peu sur les TRIGGER et les procédures stockées dans MySQL, mais je suis étonné que, alors que BEFORE INSERT et BEFORE UPDATE déclenchent pourraient modifier les données, ils ne pourraient apparemment pas causer l'échec de l'insertion / mise à jour (c.-à-d. validation). Dans ce cas particulier, j’ai réussi à obtenir que cela fonctionne en manipulant les données de manière à provoquer une duplication de la clé primaire, ce qui dans ce cas particulier avait un sens, mais n’avait pas nécessairement de sens au sens général.

Ce type de fonctionnalité est-il possible dans MySQL? Dans tout autre SGBDR (mon expérience est malheureusement limitée à MySQL)? Peut-être une syntaxe de style THROW EXCEPTION ?

Était-ce utile?

La solution

À partir de cela un article de blog

  

Déclencheurs MySQL: Comment annuler une opération INSERT, UPDATE ou DELETE avec une   déclencheur? Quelqu'un sur #mysql d’EfNet   a demandé:

     

Comment puis-je faire en sorte qu'un déclencheur annule l'opération en cas d'échec de ma règle métier?

     

Dans MySQL 5.0 et 5.1, vous devez   avoir recours à des ruses pour faire un   déclencher l'échec et livrer un sens   Message d'erreur. Le MySQL stocké   Procédure FAQ dit ceci à propos d'erreur   manipulation:

     

SP 11. Les SP ont-ils une instruction «lever» pour «générer des erreurs d'application»? Désolé, pas pour le moment. Les instructions SIGNAL et RESIGNAL standard SQL figurent sur le TODO.

     

Peut-être que MySQL 5.2 inclura SIGNAL   déclaration qui fera de ce hack   volé directement de MySQL Stored   Procédure de programmation obsolète. Quoi   est le hack? Vous allez forcer   MySQL pour essayer d'utiliser une colonne qui   n'existe pas. Laid? Oui. Le fait-il   travail? Bien sûr.

CREATE TRIGGER mytabletriggerexample
BEFORE INSERT
FOR EACH ROW BEGIN
IF(NEW.important_value) < (fancy * dancy * calculation) THEN
    DECLARE dummy INT;

    SELECT Your meaningful error message goes here INTO dummy 
        FROM mytable
      WHERE mytable.id=new.id
END IF; END;

Autres conseils

Voici comment je l’ai fait. Notez le SET NEW = 'une erreur'; . MySQL vous indiquera que la variable 'new' ne peut pas être définie sur la valeur 'Erreur: Impossible de supprimer cet élément. La table des ventes contient des enregistrements avec cet élément. '& Quot;

Vous pouvez intercepter cela dans votre code, puis afficher l'erreur résultante:)

DELIMITER $
DROP TRIGGER IF EXISTS before_tblinventoryexceptionreasons_delete $
CREATE TRIGGER before_tblinventoryexceptionreasons_delete
BEFORE DELETE ON tblinventoryexceptionreasons
FOR EACH ROW BEGIN
  IF (SELECT COUNT(*) FROM tblinventoryexceptions WHERE tblinventoryexceptions.idtblinventoryexceptionreasons = old.idtblinventoryexceptionreasons) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the inventory exception reasons table with this item.';
  END IF;
END$
DELIMITER ;

DELIMITER $
DROP TRIGGER IF EXISTS before_storesalesconfig_delete $
CREATE TRIGGER before_storesalesconfig_delete
BEFORE DELETE ON tblstoresalesconfig
FOR EACH ROW BEGIN
  IF (SELECT COUNT(*) FROM tblstoresales WHERE tblstoresales.idtblstoresalesconfig=old.idtblstoresalesconfig) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the sales table with this item.';
  END IF;
  IF (SELECT COUNT(*) FROM tblinventory WHERE tblinventory.idtblstoresalesconfig=old.idtblstoresalesconfig) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the inventory table with this item.';
  END IF;
  IF (SELECT COUNT(*) FROM tblinventoryexceptions WHERE tblinventoryexceptions.idtblstoresalesconfig=old.idtblstoresalesconfig) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the inventory exceptions table with this item.';
  END IF;
  IF (SELECT COUNT(*) FROM tblinvoicedetails WHERE tblinvoicedetails.idtblstoresalesconfig=old.idtblstoresalesconfig) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the inventory details table with this item.';
  END IF;
END$
DELIMITER ;

DELIMITER $
DROP TRIGGER IF EXISTS before_tblinvoice_delete $
CREATE TRIGGER before_tblinvoice_delete
BEFORE DELETE ON tblinvoice
FOR EACH ROW BEGIN
  IF (SELECT COUNT(*) FROM tblinvoicedetails WHERE tblinvoicedetails.idtblinvoice = old.idtblinvoice) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the inventory details table with this item.';
  END IF;
END$
DELIMITER ;

Parce que cet article arrive en tête lorsque je recherche la gestion des erreurs dans les déclencheurs MySQL, j'ai décidé de partager certaines connaissances.

En cas d'erreur, vous pouvez forcer MySQL à utiliser un SIGNAL , mais si vous ne le spécifiez pas en tant que classe sous la forme SQLEXCEPTION, rien ne se passera, car tous les SQLSTATE ne sont pas considérés comme incorrects, et même dans ce cas, vous devez vous assurer que RESIGNAL si vous avez des blocs BEGIN / END imbriqués .

Sinon, et probablement plus simplement encore, dans votre déclencheur, déclarez un gestionnaire d'exit et renvoyez l'exception.

CREATE TRIGGER `my_table_AINS` AFTER INSERT ON `my_table` FOR EACH ROW
BEGIN
    DECLARE EXIT HANDLER FOR SQLEXCEPTION
        RESIGNAL;
    DECLARE EXIT HANDLER FOR SQLWARNING
        RESIGNAL;
    DECLARE EXIT HANDLER FOR NOT FOUND
        RESIGNAL; 
    -- Do the work of the trigger.
END

Et si dans votre corps se produit une erreur, elle sera renvoyée vers le haut et sortira avec une erreur. Cela peut également être utilisé dans les procédures stockées et ainsi de suite.

Ceci fonctionne avec tout ce que la version 5.5 +.

Ceci annulera votre INSERT en générant une exception (à partir de http: // www.experts-exchange.com/Database/MySQL/Q_23788965.html )

DROP PROCEDURE IF EXISTS `MyRaiseError`$

CREATE PROCEDURE `MyRaiseError`(msg VARCHAR(62))
BEGIN
DECLARE Tmsg VARCHAR(80);
SET Tmsg = msg;
IF (CHAR_LENGTH(TRIM(Tmsg)) = 0 OR Tmsg IS NULL) THEN
SET Tmsg = 'ERROR GENERADO';
END IF;
SET Tmsg = CONCAT('@@MyError', Tmsg, '@@MyError');
SET @MyError = CONCAT('INSERT INTO', Tmsg);
PREPARE stmt FROM @MyError;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END$

Utilisation:

call MyRaiseError('Here error message!');

Ne travaillez pas dans les déclencheurs (Le SQL dynamique n'est pas autorisé dans la fonction ou le déclencheur stocké)

J'utilise une solution très sale:

Si NEW.test = 1 alors   CALL TEST_CANNOT_BE_SET_TO_1; fin si;

When test = 1 Mysql lève l'exception suivante:

PROCEDURE administratie.TEST_CANNOT_BE_SET_TO_1 n'existe pas

Pas sophistiqué mais rapide et utile.

dans MS SQL, vous pourriez le faire fonctionner avec la syntaxe appropriée:

IF UPDATE(column_name)
BEGIN
  RAISEERROR
  ROLLBACK TRAN
  RETURN
END

http://msdn.microsoft.com/en-us/magazine /cc164047.aspx

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top