IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SQL Procédural MySQL Discussion :

Syntaxe Trigger Mysql / Transact SQL de SQL Server


Sujet :

SQL Procédural MySQL

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    89
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2006
    Messages : 89
    Points : 64
    Points
    64
    Par défaut Syntaxe Trigger Mysql / Transact SQL de SQL Server
    Bonjour,

    Je suis en train d'appliquer cet excellent tutorial concernant l'héritage en BDD, et j'aimerais avoir la version MySql de ce trigger, écrit en Transact SQL de SQL Server:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    /*  Trigger sur T_CAMION_CMN pour contrôler l'insertion  */
    CREATE TRIGGER TRG_INS_T_CAMION
           ON T_CAMION_CMN
           FOR INSERT, UPDATE
    AS
    BEGIN
       DECLARE
          @errno    INTEGER,
          @errmsg   VARCHAR(255)
     
    /*  La clef de "T_VEHICULE_VHC" doit exister pour la création de "T_CAMION_CMN"  */
       IF NOT EXISTS(SELECT *
                     FROM   T_VEHICULE_VHC T
                            INNER JOIN INSERTED I
                                  ON T.VHC_ID = I.VHC_ID)
       BEGIN
          SET @errno  = 30002
          SET @errmsg = 'Clef de "T_VEHICULE_VHC" inconnu. Insertion dans "T_CAMION_CMN" impossible.'
          GOTO LBL_ERROR
       END
     
    /* l'identifiant de camion ne doit pas être utilisé par les autres tables filles */
       IF EXISTS (SELECT *
                  FROM   (SELECT VHC_ID
                          FROM T_MOTO_MTO
                          UNION ALL
                          SELECT VHC_ID
                          FROM T_VOITURE_VTR) T
                  WHERE VHC_ID IN (SELECT VHC_ID
                                   FROM   INSERTED))
       BEGIN
          SET @errno  = 30002
          SET @errmsg = 'Clef de "T_VEHICULE_VHC" déjà utilisée par ailleur. Insertion dans "T_CAMION_CMN" impossible.'
          GOTO LBL_ERROR
       END
     
       RETURN
     
    /*  Gestion d'erreurs  */
    LBL_ERROR:
        RAISERROR @errno @errmsg
        ROLLBACK TRANSACTION
    END
    GO
    Je ne suis pas sûr que MySql supporte toutes ces fonctions, notamment d'erreurs, donc je suis preneur de toute "traduction" en MySql, même simplifié.

    Merci!

  2. #2
    Membre émérite Avatar de Maximil ian
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 622
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 622
    Points : 2 973
    Points
    2 973
    Par défaut
    Salut,

    2 points me paraissent problématiques pour le passage à MySQL :

    - La levée d'erreurs : impossible sous MySQL sauf à effectuer une opération interdite (requête qui viole une contrainte de clé primaire, etc.). Par ailleurs aucun message d'erreur ne peut être renvoyé.

    - Le IF NOT EXISTS (SELECT ... ) BEGIN ... END : je ne sais pas si c'est supporté. Au pire tu peux faire un SELECT IF NOT EXISTS (SELECT ...) INTO unevariable et tester la valeur de cette variable ensuite.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    89
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2006
    Messages : 89
    Points : 64
    Points
    64
    Par défaut
    merci pour ces réponses;

    en fait, s'il n'est pas possible de lever une erreur "MySql" à partir d'un trigger, ce dernier n'a plus trop de sens... sauf à renseigner à la place une table spéciale contenant les éventuelles erreurs.

    pour le second point, pourriez-vous m'aider à affiner la syntaxe:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    SELECT (IF NOT EXISTS(SELECT *
                     FROM   T_VEHICULE_VHC T
                            INNER JOIN INSERTED I
                                  ON T.VHC_ID = I.VHC_ID)) AS MAVARIABLE
     
    IF MAVARIABLE = TRUE
      INSERT INTO ERROR_TABLE (MSG) VALUES ('Clef de "T_VEHICULE_VHC" inconnu. Insertion dans "T_CAMION_CMN" impossible.');
    Merci!

  4. #4
    Membre émérite Avatar de Maximil ian
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 622
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 622
    Points : 2 973
    Points
    2 973
    Par défaut
    Citation Envoyé par Flashball Voir le message
    en fait, s'il n'est pas possible de lever une erreur "MySql" à partir d'un trigger, ce dernier n'a plus trop de sens... sauf à renseigner à la place une table spéciale contenant les éventuelles erreurs.
    Si car le but est quand même d'empêcher l'insertion, ce qui peut être fait en exécutant un ordre SQL illégal dans le trigger.

    Citation Envoyé par Flashball Voir le message
    pour le second point, pourriez-vous m'aider à affiner la syntaxe:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    SELECT (IF NOT EXISTS(SELECT *
                     FROM   T_VEHICULE_VHC T
                            INNER JOIN INSERTED I
                                  ON T.VHC_ID = I.VHC_ID)) AS MAVARIABLE
     
    IF MAVARIABLE = TRUE
      INSERT INTO ERROR_TABLE (MSG) VALUES ('Clef de "T_VEHICULE_VHC" inconnu. Insertion dans "T_CAMION_CMN" impossible.');
    Oups, je me suis peut-être un peu avancé sur la syntaxe... Essaie quelque chose du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    SELECT COUNT (*)
                     FROM   T_VEHICULE_VHC T
                     WHERE T.VHC_ID = NEW.VHC_ID
    INTO mavariable;
     
    IF mavariable = 0 THEN
      INSERT INTO ERROR_TABLE (MSG) VALUES ('Clef de "T_VEHICULE_VHC" inconnu. Insertion dans "T_CAMION_CMN" impossible.');
    /* + ici ordre illégal qui interromp le INSERT */
    END IF;
    Autre chose : un trigger FOR INSERT, UPDATE n'est pas possible sous MySQL. Il faut en créer un pour INSERT et un pour UPDATE.

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    89
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2006
    Messages : 89
    Points : 64
    Points
    64
    Par défaut
    Bonjour,

    Merci pour cette réponse, mais je n'arrive pas exécuter ce trigger. Pour simplifier la suite, j'utilise mes vraies tables et colonnes plutôt que celles du tuto. Il s'agit de tables 'admin', 'customer' et 'referent' censées hériter de la table 'author'. Les identifiants des tables 'admin', 'customer' et 'referent' se nomment tous 'author_id' et sont des clefs étrangères pointant vers la colonne 'id' de la table 'author'.

    Voilà le trigger complet de l'insertion dans la table 'admin':

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    DELIMITER //
    CREATE TRIGGER TRG_INS_ADMIN ON ADMIN FOR INSERT
    BEGIN
     
    	--  La clef de "AUTHOR" doit exister pour la création de "ADMIN"  --
    	SELECT COUNT (*)
    		FROM   AUTHOR T
    		WHERE T.ID = NEW.AUTHOR_ID
    	INTO mavariable;
     
    	IF mavariable = 0 THEN
    	  INSERT INTO ERROR_TABLE (MSG) VALUES ('Clef de "AUTHOR" inconnu. Insertion dans "ADMIN" théoriquement impossible.');
    	  /* + ici ordre illégal qui interromp le INSERT */
    	END IF;
    END
    //
    DELIMITER ;
    Quand j'exécute ce code sous phpMyAdmin, voici la réponse:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    MySQL said: Documentation
    #1064 - 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 'ON ADMIN FOR INSERT
    BEGIN
     
            SELECT COUNT (*)
            FROM   AUTHOR T
            WHERE T.I' at line 1
    J'ai aussi essayé 'CREATE TRIGGER (...) FOR EACH ROW INSERT' comme indiqué dans le manuel, mais ca ne change rien.

    Merci pour votre aide!

  6. #6
    Membre émérite Avatar de Maximil ian
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 622
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 622
    Points : 2 973
    Points
    2 973
    Par défaut
    La syntaxe est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    CREATE TRIGGER trigger_name trigger_time trigger_event
        ON tbl_name FOR EACH ROW trigger_stmt
    trigger_time étant BEFORE ou AFTER et trigger_event l'ordre SQL (SELECT, INSERT...)

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    89
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2006
    Messages : 89
    Points : 64
    Points
    64
    Par défaut
    merci, voilà ce qui marche:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    CREATE TRIGGER `module_news`.`TRG_INS_ADMIN` BEFORE INSERT ON `module_news`.`admin`
     FOR EACH ROW BEGIN
        INSERT INTO error_table SET msg = 'test';
      END
    par contre, quand je complexifie un tout petit plus:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    DELIMITER //
    CREATE TRIGGER `module_news`.`TRG_INS_ADMIN` BEFORE INSERT ON `module_news`.`admin`
     FOR EACH ROW BEGIN
        SELECT COUNT(AUTHOR_ID) FROM author INTO mavar;
        IF mavar = 0 THEN
          INSERT INTO error_table SET msg = 'Erreur';
        END IF;
      END
    //
    J'ai une erreur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #1327 - Undeclared variable: mavar
    J'avance pas vite...

  8. #8
    Rédacteur/Modérateur

    Avatar de Antoun
    Homme Profil pro
    Architecte décisionnel
    Inscrit en
    Octobre 2006
    Messages
    6 284
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte décisionnel
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2006
    Messages : 6 284
    Points : 11 738
    Points
    11 738
    Par défaut
    Bah, il faut déclarer la variable locale :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    DELIMITER //
    CREATE TRIGGER `module_news`.`TRG_INS_ADMIN` BEFORE INSERT ON `module_news`.`admin`
     FOR EACH ROW 
     BEGIN
     DECLARE mavar INT ;
        SELECT COUNT(AUTHOR_ID) FROM author INTO mavar;
        IF mavar = 0 THEN
          INSERT INTO error_table SET msg = 'Erreur';
        END IF;
      END
    //
    Alternative sans variable :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    DELIMITER //
    CREATE TRIGGER `module_news`.`TRG_INS_ADMIN` BEFORE INSERT ON `module_news`.`admin`
     FOR EACH ROW 
     BEGIN
        IF (SELECT COUNT(AUTHOR_ID) FROM author) = 0 THEN
          INSERT INTO error_table SET msg = 'Erreur';
        END IF;
      END
    //

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    89
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2006
    Messages : 89
    Points : 64
    Points
    64
    Par défaut
    Merci, çà marche très bien maintenant!

    Version complète du tuto adaptée pour MySql (à adapter aux histoires de camion, voiture, moto...):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    --  Trigger sur ADMIN pour contrôler l'insertion  --
    DROP TRIGGER IF EXISTS `module_news`.`TRG_INS_ADMIN`//
    CREATE TRIGGER `module_news`.`TRG_INS_ADMIN` BEFORE INSERT ON `module_news`.`admin`
     FOR EACH ROW BEGIN
     DECLARE mavar INT ;
        -- La clef de "AUTHOR" doit exister pour la création de "ADMIN"
        SELECT COUNT(AUTHOR_ID) FROM author INTO mavar;
        IF mavar = 0 THEN
          INSERT INTO error_table SET msg = 'La clef de "AUTHOR" doit exister pour la création de "ADMIN"';
          INSERT INTO error_table SET ID = 'ordre illégal';
        END IF;
        --  La clef de "AUTHOR" ne doit pas être utilisée par les autres tables filles --
        SELECT COUNT(T.AUTHOR_ID)
                   FROM   (SELECT AUTHOR_ID
                           FROM customer
                           UNION ALL
                           SELECT AUTHOR_ID
                           FROM referent) T
                   WHERE T.AUTHOR_ID  = NEW.AUTHOR_ID
    	       INTO mavar;
        IF mavar > 0 THEN
          INSERT INTO error_table SET msg = 'La clef de "AUTHOR" ne doit pas être utilisée par les autres tables filles';
          INSERT INTO error_table SET ID = 'ordre illégal';
         END IF;
      END
    //

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Trigger MySql to Sql Server
    Par olifile dans le forum SQL Procédural
    Réponses: 0
    Dernier message: 07/07/2009, 01h08
  2. gérer les transactions avec php/sql server
    Par loukili81 dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 15/05/2007, 17h39
  3. Réponses: 4
    Dernier message: 16/04/2007, 09h54
  4. [PL/SQL] Creation de triggers dans transaction
    Par globeriding dans le forum Oracle
    Réponses: 15
    Dernier message: 07/02/2006, 11h33
  5. S'initier sur Mysql pour faire du SQL Server
    Par bigjeff dans le forum Langage SQL
    Réponses: 5
    Dernier message: 11/11/2005, 14h38

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo