Précédent   Forum des professionnels en informatique > Bases de données > MySQL > SQL Procédural
SQL Procédural Forum d'entraide sur les triggers, les procédures stockées et les fonctions en MySQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 27/05/2011, 09h19   #1
Membre confirmé
 
Avatar de Pymento
 
Homme
Ingé. Info.
Inscription : janvier 2008
Messages : 338
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 24
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Ingé. Info.

Informations forums :
Inscription : janvier 2008
Messages : 338
Points : 273
Points : 273
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 :
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.
__________________
Memento Quia Pulvis Es, Et In Pulverem ReverteriS
Pymento est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/05/2011, 09h31   #2
Membre Expert
 
Homme Eric Dureuil
Développeur informatique
Inscription : avril 2011
Messages : 852
Détails du profil
Informations personnelles :
Nom : Homme Eric Dureuil
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 : 852
Points : 1 330
Points : 1 330
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
__________________
Eric Dureuil, développeur web, c/c++, java indépendant
soyons
pensez à mettre et
ericd69 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/05/2011, 09h43   #3
Membre confirmé
 
Avatar de Pymento
 
Homme
Ingé. Info.
Inscription : janvier 2008
Messages : 338
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 24
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Ingé. Info.

Informations forums :
Inscription : janvier 2008
Messages : 338
Points : 273
Points : 273
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.
__________________
Memento Quia Pulvis Es, Et In Pulverem ReverteriS
Pymento est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/05/2011, 09h58   #4
Membre Expert
 
Homme Eric Dureuil
Développeur informatique
Inscription : avril 2011
Messages : 852
Détails du profil
Informations personnelles :
Nom : Homme Eric Dureuil
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 : 852
Points : 1 330
Points : 1 330
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
__________________
Eric Dureuil, développeur web, c/c++, java indépendant
soyons
pensez à mettre et
ericd69 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/05/2011, 10h04   #5
Membre confirmé
 
Avatar de Pymento
 
Homme
Ingé. Info.
Inscription : janvier 2008
Messages : 338
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 24
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Ingé. Info.

Informations forums :
Inscription : janvier 2008
Messages : 338
Points : 273
Points : 273
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.
__________________
Memento Quia Pulvis Es, Et In Pulverem ReverteriS
Pymento est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/05/2011, 10h53   #6
Membre Expert
 
Homme Eric Dureuil
Développeur informatique
Inscription : avril 2011
Messages : 852
Détails du profil
Informations personnelles :
Nom : Homme Eric Dureuil
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 : 852
Points : 1 330
Points : 1 330
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...
__________________
Eric Dureuil, développeur web, c/c++, java indépendant
soyons
pensez à mettre et
ericd69 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/05/2011, 11h33   #7
Membre confirmé
 
Avatar de Pymento
 
Homme
Ingé. Info.
Inscription : janvier 2008
Messages : 338
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 24
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Ingé. Info.

Informations forums :
Inscription : janvier 2008
Messages : 338
Points : 273
Points : 273
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 :
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.
__________________
Memento Quia Pulvis Es, Et In Pulverem ReverteriS
Pymento est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/05/2011, 15h18   #8
Membre Expert
 
Homme Eric Dureuil
Développeur informatique
Inscription : avril 2011
Messages : 852
Détails du profil
Informations personnelles :
Nom : Homme Eric Dureuil
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 : 852
Points : 1 330
Points : 1 330
la solution est de passer par une procédure stockée alors...
__________________
Eric Dureuil, développeur web, c/c++, java indépendant
soyons
pensez à mettre et
ericd69 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/05/2011, 15h54   #9
Membre confirmé
 
Avatar de Pymento
 
Homme
Ingé. Info.
Inscription : janvier 2008
Messages : 338
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 24
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Ingé. Info.

Informations forums :
Inscription : janvier 2008
Messages : 338
Points : 273
Points : 273
J'obtient ça comme message d'erreur

Code :
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 :
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.
__________________
Memento Quia Pulvis Es, Et In Pulverem ReverteriS
Pymento est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/05/2011, 16h11   #10
Membre Expert
 
Homme Eric Dureuil
Développeur informatique
Inscription : avril 2011
Messages : 852
Détails du profil
Informations personnelles :
Nom : Homme Eric Dureuil
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 : 852
Points : 1 330
Points : 1 330
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 :
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;
__________________
Eric Dureuil, développeur web, c/c++, java indépendant
soyons
pensez à mettre et
ericd69 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/05/2011, 14h40   #11
Membre confirmé
 
Avatar de Pymento
 
Homme
Ingé. Info.
Inscription : janvier 2008
Messages : 338
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 24
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Ingé. Info.

Informations forums :
Inscription : janvier 2008
Messages : 338
Points : 273
Points : 273
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 :
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.
__________________
Memento Quia Pulvis Es, Et In Pulverem ReverteriS
Pymento est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/05/2011, 14h50   #12
Membre Expert
 
Homme Eric Dureuil
Développeur informatique
Inscription : avril 2011
Messages : 852
Détails du profil
Informations personnelles :
Nom : Homme Eric Dureuil
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 : 852
Points : 1 330
Points : 1 330
autan pour moi, j'avais pompé le début de ton code sans le changer :p

Code sql :
CREATE PROCEDURE cascade_delete (IN current_id int(4))
__________________
Eric Dureuil, développeur web, c/c++, java indépendant
soyons
pensez à mettre et
ericd69 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/05/2011, 15h21   #13
Membre confirmé
 
Avatar de Pymento
 
Homme
Ingé. Info.
Inscription : janvier 2008
Messages : 338
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 24
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Ingé. Info.

Informations forums :
Inscription : janvier 2008
Messages : 338
Points : 273
Points : 273
Exact, en revanche, ça serait trop simple de fonctionner directement !
Code :
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
__________________
Memento Quia Pulvis Es, Et In Pulverem ReverteriS
Pymento est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/05/2011, 15h24   #14
Membre Expert
 
Homme Eric Dureuil
Développeur informatique
Inscription : avril 2011
Messages : 852
Détails du profil
Informations personnelles :
Nom : Homme Eric Dureuil
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 : 852
Points : 1 330
Points : 1 330
tu as quelle version de mysql?
__________________
Eric Dureuil, développeur web, c/c++, java indépendant
soyons
pensez à mettre et
ericd69 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/05/2011, 15h26   #15
Membre confirmé
 
Avatar de Pymento
 
Homme
Ingé. Info.
Inscription : janvier 2008
Messages : 338
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 24
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Ingé. Info.

Informations forums :
Inscription : janvier 2008
Messages : 338
Points : 273
Points : 273
Apache/2.2.17 (Win32) PHP/5.3.6
Version du client MySQL: mysqlnd 5.0.8-dev - 20102224 - $Revision: 308673 $
__________________
Memento Quia Pulvis Es, Et In Pulverem ReverteriS
Pymento est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/05/2011, 15h57   #16
Membre confirmé
 
Avatar de Pymento
 
Homme
Ingé. Info.
Inscription : janvier 2008
Messages : 338
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 24
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Ingé. Info.

Informations forums :
Inscription : janvier 2008
Messages : 338
Points : 273
Points : 273
Enfin.. non j'ai trouvé ça plutot, c'est écrit en plus gros:

MYSQL 5.5.10
__________________
Memento Quia Pulvis Es, Et In Pulverem ReverteriS
Pymento est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/05/2011, 16h47   #17
Membre Expert
 
Homme Eric Dureuil
Développeur informatique
Inscription : avril 2011
Messages : 852
Détails du profil
Informations personnelles :
Nom : Homme Eric Dureuil
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 : 852
Points : 1 330
Points : 1 330
ç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 :
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;
__________________
Eric Dureuil, développeur web, c/c++, java indépendant
soyons
pensez à mettre et
ericd69 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/05/2011, 17h03   #18
Membre confirmé
 
Avatar de Pymento
 
Homme
Ingé. Info.
Inscription : janvier 2008
Messages : 338
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 24
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Ingé. Info.

Informations forums :
Inscription : janvier 2008
Messages : 338
Points : 273
Points : 273
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 :
1
2
3
4
 
 
#1326 - Cursor is not open
CALL cascade_delete( 5 )

Je pense que ça a un rapport avec cette ligne:
Code :
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
__________________
Memento Quia Pulvis Es, Et In Pulverem ReverteriS
Pymento est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/05/2011, 17h27   #19
Membre Expert
 
Homme Eric Dureuil
Développeur informatique
Inscription : avril 2011
Messages : 852
Détails du profil
Informations personnelles :
Nom : Homme Eric Dureuil
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 : 852
Points : 1 330
Points : 1 330
oui j'ai oublié de mettre l'ouverture et la fermeture, dernière rectification

Code sql :
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;
__________________
Eric Dureuil, développeur web, c/c++, java indépendant
soyons
pensez à mettre et
ericd69 est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 30/05/2011, 17h36   #20
Membre confirmé
 
Avatar de Pymento
 
Homme
Ingé. Info.
Inscription : janvier 2008
Messages : 338
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 24
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Ingé. Info.

Informations forums :
Inscription : janvier 2008
Messages : 338
Points : 273
Points : 273
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
__________________
Memento Quia Pulvis Es, Et In Pulverem ReverteriS
Pymento est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 19h57.


 
 
 
 
Partenaires

Hébergement Web