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 :

Eye of the trigger


Sujet :

SQL Procédural MySQL

  1. #1
    Membre éclairé Avatar de Pymento
    Homme Profil pro
    Ingé. Info.
    Inscrit en
    Janvier 2008
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingé. Info.

    Informations forums :
    Inscription : Janvier 2008
    Messages : 366
    Par défaut Eye of the trigger
    Bonjour j'ouvre mon nouveau problème dans un nouveau fil, l'ancien commençant à être un peu long.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    DELIMITER $$
    CREATE TRIGGER delete_cascade_element
    AFTER DELETE ON T1
    FOR EACH ROW
    BEGIN
    DELETE FROM T2 WHERE T2_id=Old.T1_id;
    END$$
    DELIMITER ;
    J'ai deux table T1 et T2.
    Une entrée T1 a une colonne parent qui pointe sur une autre entrée T1.
    T2 à pour identifiant le même id que l'entrée sur T1 à laquelle il correspond.

    T1 a la propriété on cascade delete activé, et qui fonctionne.



    Mon pb -> le trigger fonctionne partiellement, càd lors d'une suppression d'une entrée sur T1, la suppression se passe sur l'entrée correspondante sur T2.
    En revanche si la suppression est soumise "à la cascade" ça ne marche pas.

    Ou est mon erreur..?

    Merci bien.

  2. #2
    Membre Expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Billets dans le blog
    1
    Par défaut
    comme je l'ai dit dans l'autre post tu dois le paramètrer au niveau de la colonne concernée et en myisam je suis pas sur que ça marche... il me semble que tu dois être en innodb

  3. #3
    Membre éclairé Avatar de Pymento
    Homme Profil pro
    Ingé. Info.
    Inscrit en
    Janvier 2008
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingé. Info.

    Informations forums :
    Inscription : Janvier 2008
    Messages : 366
    Par défaut
    T1 est en innoDB.
    T2 en MyIsam.

    Quand je fais un delete sur T1 et que l'entrée a un fils(qui se supprime bien), mysql ne considère pas ça comme une condition pour "rentrer" dans mon trigger ?

    Je trouve ça illogique.
    ça voudrait dire que un delete et un delete issu d'une cascade ne sont pas fait de la même manière.

  4. #4
    Membre Expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Billets dans le blog
    1
    Par défaut
    ton trigger est local à une table

    la cascade est un comportement d'intégrité référentielle

    donc pas du tout les même choses même si ça touche à une action commune qui les déclenche

  5. #5
    Membre éclairé Avatar de Pymento
    Homme Profil pro
    Ingé. Info.
    Inscrit en
    Janvier 2008
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingé. Info.

    Informations forums :
    Inscription : Janvier 2008
    Messages : 366
    Par défaut
    Donc la seule solution, serait de virer mes foreign key et mon cascade et de mettre un trigger à la place

    on delete, delete fils ET delete sur T2.

    ça semble propre mais niveau performance, j'en ai aucune idée.

  6. #6
    Membre Expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Billets dans le blog
    1
    Par défaut
    lit ça : contrainte de cascade

    tu peux les laisser, ça les auto indexe au moins...

    mais sinon je pense que c'est la solution...

    ou change le moteur de ta table myisam...

  7. #7
    Membre éclairé Avatar de Pymento
    Homme Profil pro
    Ingé. Info.
    Inscrit en
    Janvier 2008
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingé. Info.

    Informations forums :
    Inscription : Janvier 2008
    Messages : 366
    Par défaut
    Je ne peux pas changer le MyIsam, j'en ai besoin pour faire de l'indexage fullText (chose qu'innoDB ne fait pas)

    Je n'arrive pas, ni en conservant le cascading ni en l'enlevant, à mettre en place un trigger qui me supprime mon entrée fille.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    DELIMITER $$
    CREATE TRIGGER delete_cascade_element
    BEFORE DELETE ON elements
    FOR EACH ROW
    BEGIN
    DELETE FROM elements WHERE Old.id=parent;
    END$$
    DELIMITER ;
    J'ai essayé avec AFTER à la place de BEFORE, mais sans succès.

  8. #8
    Membre Expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Billets dans le blog
    1
    Par défaut
    la solution est de passer par une procédure stockée alors...

  9. #9
    Membre éclairé Avatar de Pymento
    Homme Profil pro
    Ingé. Info.
    Inscrit en
    Janvier 2008
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingé. Info.

    Informations forums :
    Inscription : Janvier 2008
    Messages : 366
    Par défaut
    J'obtient ça comme message d'erreur

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
     
    #1442 - Can't update table 'table' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
    Donc à ce que j'ai pu lire, mysql bloque la table et donc ne permet pas de faire un trigger d'une table sur elle même... j'espère avoir lu quelque chose de faux..
    Alors deux solution s'offrent à moi (voire 3 si je continue à chercher):
    la première changer de sgbd...
    Ou alors faire une procédure stockée récursive.
    Du genre :
    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
    delimiter $$
    
    CREATE PROCEDURE cascade_delete (current_id)
    DECLARE ids int[];
    BEGIN
    
     ids = SELECT id FROM elements WHERE parent=current_id;
    foreach ids as value
       begin
          cascade_delete(value)
       end
    DELETE FROM elements WHERE id = current_id
    END
    $$
    Mais bon la partie en gras je ne sais pas dutout comment la mettre en place, et si c'est faisable.

  10. #10
    Membre Expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Billets dans le blog
    1
    Par défaut
    pas du tout comme ça

    les tableaux n'existent pas en mysql...

    tu dois faire au moins un set @@max_sp_recursion_depth=255; pour permettre le maximum de niveau de récursion (moins si tu sais la profondeur maximum)...


    Code sql : 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
    delimiter $$
     
    CREATE PROCEDURE cascade_delete (current_id)
    begin
    	declare i int(4);
    	declare done bool default 0;
    	declare lit cursor for select id from elements where parent=current_id;
    	declare continue handler for SQLSTATE '02000' set done=1;
    	set @@max_sp_recursion_depth=255;
    	repeat
    		fetch lit into i;
    		if not done then
    			call cascade_delete(i);
    		end if;
    	until done end repeat;
    	delete from elements where id=current_id;
    end$$
     
    delimiter;

  11. #11
    Membre éclairé Avatar de Pymento
    Homme Profil pro
    Ingé. Info.
    Inscrit en
    Janvier 2008
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingé. Info.

    Informations forums :
    Inscription : Janvier 2008
    Messages : 366
    Par défaut
    Merci pour cette procédure.
    Même si y'a 2-3 lignes que je ne comprend pas encore, je viens de l'essayer.
    Et ça me crache une erreur:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    MySQL a répondu: 
     
    #1064 - Erreur de syntaxe près de ')
    BEGIN
        declare i int(4);
        declare done bool DEFAULT 0;
        declare lit cursor' à la ligne 1
    Et ça me met la croix rouge à hauteur du i dans le rappel de la procédure.

  12. #12
    Membre Expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Billets dans le blog
    1
    Par défaut
    autan pour moi, j'avais pompé le début de ton code sans le changer :p

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    CREATE PROCEDURE cascade_delete (in current_id int(4))

  13. #13
    Membre éclairé Avatar de Pymento
    Homme Profil pro
    Ingé. Info.
    Inscrit en
    Janvier 2008
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingé. Info.

    Informations forums :
    Inscription : Janvier 2008
    Messages : 366
    Par défaut
    Exact, en revanche, ça serait trop simple de fonctionner directement !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
     Cannot load from mysql.proc. The table is probably corrupted
    a chaque fois. (avec un DROP PROCEDURE cascade_delete aussi)

    j'ai regardé un peu sur le net et ils disent de faire un mysql_upgrade, et sur phpmyadmin... je sais pas ou le faire ou même si c'est la bonne solution

  14. #14
    Membre Expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Billets dans le blog
    1
    Par défaut
    tu as quelle version de mysql?

  15. #15
    Membre éclairé Avatar de Pymento
    Homme Profil pro
    Ingé. Info.
    Inscrit en
    Janvier 2008
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingé. Info.

    Informations forums :
    Inscription : Janvier 2008
    Messages : 366
    Par défaut
    Apache/2.2.17 (Win32) PHP/5.3.6
    Version du client MySQL: mysqlnd 5.0.8-dev - 20102224 - $Revision: 308673 $

  16. #16
    Membre éclairé Avatar de Pymento
    Homme Profil pro
    Ingé. Info.
    Inscrit en
    Janvier 2008
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingé. Info.

    Informations forums :
    Inscription : Janvier 2008
    Messages : 366
    Par défaut
    Enfin.. non j'ai trouvé ça plutot, c'est écrit en plus gros:

    MYSQL 5.5.10

  17. #17
    Membre Expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Billets dans le blog
    1
    Par défaut
    ça les prend en charge...

    bon le truc complet qui doit marcher avec : db le nom de la base qui contiendra la procédure stockée

    Code sql : 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
    use db;
    drop procedure if exists cascade_delete;
    delimiter $$
     
    CREATE PROCEDURE cascade_delete(in current_id int(4))
    begin
    	declare i int(4);
    	declare done bool DEFAULT 0;
    	declare lit cursor FOR SELECT id FROM elements WHERE parent=current_id;
    	declare continue handler FOR SQLSTATE '02000' SET done=1;
    	SET @@max_sp_recursion_depth=255;
    	repeat
    		fetch lit INTO i;
    		IF NOT done then
    			call cascade_delete(i);
    		end IF;
    	until done end repeat;
    	DELETE FROM elements WHERE id=current_id;
    end$$
     
    delimiter;

  18. #18
    Membre éclairé Avatar de Pymento
    Homme Profil pro
    Ingé. Info.
    Inscrit en
    Janvier 2008
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingé. Info.

    Informations forums :
    Inscription : Janvier 2008
    Messages : 366
    Par défaut
    J'ai fais un avec l'invite de commande, et ça m'a donc effectivement laisser enregistrer ma procédure.

    Par contre quand je l'exécute ça me dit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
     
    #1326 - Cursor is not open
    CALL cascade_delete( 5 )

    Je pense que ça a un rapport avec cette ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    declare continue handler FOR SQLSTATE '02000' SET done=1;
    A ce que j'ai pu lire, y'a une histoire de fermeture sans ouverture préalable du curseur

  19. #19
    Membre Expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Billets dans le blog
    1
    Par défaut
    oui j'ai oublié de mettre l'ouverture et la fermeture, dernière rectification

    Code sql : 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
    USE db;
    DROP procedure IF EXISTS cascade_delete;
    delimiter $$
     
    CREATE PROCEDURE cascade_delete(IN current_id int(4))
    begin
    	declare i int(4);
    	declare done bool DEFAULT 0;
    	declare lit cursor FOR SELECT id FROM elements WHERE parent=current_id;
    	declare continue handler FOR SQLSTATE '02000' SET done=1;
    	SET @@max_sp_recursion_depth=255;
    	open lit;
    	repeat
    		fetch lit INTO i;
    		IF NOT done then
    			call cascade_delete(i);
    		end IF;
    	until done end repeat;
    	close lit;
    	DELETE FROM elements WHERE id=current_id;
    end$$
     
    delimiter;

  20. #20
    Membre éclairé Avatar de Pymento
    Homme Profil pro
    Ingé. Info.
    Inscrit en
    Janvier 2008
    Messages
    366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingé. Info.

    Informations forums :
    Inscription : Janvier 2008
    Messages : 366
    Par défaut
    PARFAIT !
    ça marche !
    Merci bcp .

    j'ai simplement à rajouter une ligne delete pour agir sur l'autre table comme je le souhaitais au début.

    Je met le post en résolu

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [Projet en cours] Dungeon Eye - Remake de Eye of the Beholder II
    Par iliak dans le forum Projets
    Réponses: 5
    Dernier message: 01/08/2011, 15h56
  2. Unable to list the triggers sqlstate = 42703
    Par The Ditch dans le forum PowerAMC
    Réponses: 0
    Dernier message: 23/05/2011, 19h53
  3. [Recrutement] Scénariste / Level Designer pour un clone de Eye of the Beholder II
    Par iliak dans le forum Projets
    Réponses: 1
    Dernier message: 18/05/2011, 01h29

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