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 13/01/2011, 19h28   #1
Invité de passage
 
Thomas Denoncin
Inscription : janvier 2011
Messages : 3
Détails du profil
Informations personnelles :
Nom : Thomas Denoncin

Informations forums :
Inscription : janvier 2011
Messages : 3
Points : 0
Points : 0
Par défaut PREPARE dans une proc stock

Bonjour à tous.
Je me permets de faire un peu de nécromancie de topic dans la mesure où ce sujet correspond tout à fait à ce que j'essaie de faire.

Petite présentation du contexte tout d'abord :
J'ai besoin de faire des requêtes avec un nom de table variable dans une procédure stockée en mysql. Après quelques recherches sur le web, il apparait que pour ce faire, je dois utiliser un PREPARE statement.

Courageux et optimiste, je me lance. Oui mais voilà, je récupère une erreur :
"#1312 - PROCEDURE 3620t01.maProcedure can't return a result set in the given context"
Damn..

Après pas mal de recherches cette fois-ci, je retiens que :
-Il n'est pas possible de faire d'utiliser un PREPARE statement dans une fonction ou une procédure stockée SAUF pour les procédures stockées justement DEPUIS la version 5.0.13 de mysql.
Or, je travaille sur la version 5.0.51.

Du coup je ne vois vraiment pas d'où peut venir le soucis.
Si une bonne âme avait une idée..

Pour info, je mets ici la procédure de test que j'ai faite, basée sur celle utilisée plus haut dans ce topic :

Code :
1
2
3
4
5
6
7
delimiter |
CREATE PROCEDURE maProcedure()
BEGIN
SET @sqlCMD =  CONCAT('select * from ', 'tickets_J');
PREPARE stmt FROM @sqlCMD;
EXECUTE stmt ;
END
et l'erreur :

Code :
#1312 - PROCEDURE 3620t01.maProcedure can't return a result set in the given context
Ps : Je précise; si besoin est, que j'ai l'erreur sur le CALL de ma procédure stockée, et pas à la création

Merci d'avance.

Thomas
Gladolfera est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/01/2011, 22h40   #2
Rédacteur/Modérateur

 
Avatar de Antoun
 
Homme Antoine Dinimant
Consultant en Business Intelligence
Inscription : octobre 2006
Messages : 5 854
Détails du profil
Informations personnelles :
Nom : Homme Antoine Dinimant
Âge : 42
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Consultant en Business Intelligence
Secteur : Conseil

Informations forums :
Inscription : octobre 2006
Messages : 5 854
Points : 9 559
Points : 9 559
Les procédures stockées de MySQL ne sont pas faites pour envoyer un jeu de résultat... sur des cas simples, ça marche quand même, mais comme elles ne sont pas faites pour ça, ça plante à la moindre petite complexité...

Le contournement habituel est de faire un CREATE SELECT :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
 
delimiter |
CREATE PROCEDURE maProcedure()
BEGIN
SET @sqlCMD =  CONCAT('create table tmp_resu select * from ', 'tickets_J');
PREPARE stmt FROM @sqlCMD;
EXECUTE stmt ;
END |
 
delimiter ;
 
SELECT * FROM tmp_resu ;
__________________
Antoun
Expert SQL, BO, Essbase

La bible d'Essbase est parue !
Antoun est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 14/01/2011, 10h07   #3
Invité de passage
 
Thomas Denoncin
Inscription : janvier 2011
Messages : 3
Détails du profil
Informations personnelles :
Nom : Thomas Denoncin

Informations forums :
Inscription : janvier 2011
Messages : 3
Points : 0
Points : 0
Ok, merci beaucoup, c'est bon à savoir.

Mais du coup mon problème réel persiste. Je m'explique :
Le code avec la requete SELECT n'était qu'un test pour tester les PEPARE statement, ce que je cherche en réalité à faire est un INSERT, comme ceci :
Code :
1
2
3
4
5
6
7
8
 
delimiter |
CREATE PROCEDURE maProcedure(maTable)
BEGIN
SET @sqlCMD =  CONCAT("INSERT INTO ",maTable," VALUES('valeur1','valeur2')");
PREPARE stmt FROM @sqlCMD;
EXECUTE stmt ;
END |
Du coup à priori il n'y a pas de jeu de résultat renvoyé.
Mais j'ai tout de même l'erreur.
Qu'est-ce que j'ai manqué ?

Merci d'avance,
Thomas
Gladolfera est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/01/2011, 15h02   #4
Rédacteur/Modérateur

 
Avatar de Antoun
 
Homme Antoine Dinimant
Consultant en Business Intelligence
Inscription : octobre 2006
Messages : 5 854
Détails du profil
Informations personnelles :
Nom : Homme Antoine Dinimant
Âge : 42
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Consultant en Business Intelligence
Secteur : Conseil

Informations forums :
Inscription : octobre 2006
Messages : 5 854
Points : 9 559
Points : 9 559
ça marche chez moi, à condition de corriger ta syntaxe pour avoir un CREATE qui fonctionne :

Code :
1
2
3
4
5
6
7
8
9
delimiter |
CREATE PROCEDURE maProcedure(IN maTable VARCHAR(30))
BEGIN
SET @sqlCMD =  CONCAT('INSERT INTO ', maTable, ' VALUES(''valeur1'', ''valeur2'')');
PREPARE stmt FROM @sqlCMD;
EXECUTE stmt ;
END |

delimiter ;
Vérification :
Code :
1
2
3
4
5
6
7
8
9
10
11
 
CREATE TABLE test(a varchar(50), b varchar(50)) ;
call maprocedure 'test' ;
SELECT * FROM test ;
 
+---------+---------+
| a       | b       |
+---------+---------+
| valeur1 | valeur2 |
+---------+---------+
1 row IN SET (0.04 sec)
__________________
Antoun
Expert SQL, BO, Essbase

La bible d'Essbase est parue !
Antoun est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2011, 11h03   #5
Invité de passage
 
Thomas Denoncin
Inscription : janvier 2011
Messages : 3
Détails du profil
Informations personnelles :
Nom : Thomas Denoncin

Informations forums :
Inscription : janvier 2011
Messages : 3
Points : 0
Points : 0
Damn, ça ne fonctionne pas chez moi, même une fois le code corrigé..
Aurais-tu une idée de la cause du problème ?
Y a-t-il une solution de contournement ?

Merci d'avance,
Thomas
Gladolfera est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2011, 13h02   #6
Rédacteur/Modérateur

 
Avatar de Antoun
 
Homme Antoine Dinimant
Consultant en Business Intelligence
Inscription : octobre 2006
Messages : 5 854
Détails du profil
Informations personnelles :
Nom : Homme Antoine Dinimant
Âge : 42
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Consultant en Business Intelligence
Secteur : Conseil

Informations forums :
Inscription : octobre 2006
Messages : 5 854
Points : 9 559
Points : 9 559
Peux-tu dire exactement ce qui ne marche pas (compilation, exécution) et nous donner le
message d'erreur ?
__________________
Antoun
Expert SQL, BO, Essbase

La bible d'Essbase est parue !
Antoun est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/01/2011, 10h10   #7
Invité régulier
 
Jerome Soulier
Inscription : décembre 2010
Messages : 12
Détails du profil
Informations personnelles :
Nom : Jerome Soulier

Informations forums :
Inscription : décembre 2010
Messages : 12
Points : 9
Points : 9
Envoyer un message via MSN à jerome93sx


Merci Antoun pour ton information.

Je cherchais à réaliser un PREPARE dans une procédure stockée.
Mon erreur venait du jeu de résultat retourné dans mon SELECT.


Ton code ===>

Code :
1
2
3
4
5
6
7
8
9
10
11
12
 
delimiter |
CREATE PROCEDURE maProcedure()
BEGIN
SET @sqlCMD =  CONCAT('create table tmp_resu select * from ', 'tickets_J');
PREPARE stmt FROM @sqlCMD;
EXECUTE stmt ;
END |
 
delimiter ;
 
SELECT * FROM tmp_resu ;
===> Marche parfaitement... De plus je rajoute cette astuce de codage dans ma production actuelle.


Un grand M.E.R.C.I.

Jérôme.

jerome93sx est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/04/2011, 17h36   #8
Membre Expert
 
Homme Eric Dureuil
Développeur informatique
Inscription : avril 2011
Messages : 839
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 : 839
Points : 1 312
Points : 1 312
Les procédure stockée PEUVENT retourner directement autan de résultats que tu veux, il suffit d'avoir un client mysql avec la bonne version ou d'utiliser un connecteur qui DOIT permettre d'exécuter des requêtes avec un set de résultats multiples...

La seule limite avec les PREPARE c'est la récursivité avec le même nom de statement stockant l'action à faire et tout ce qui est interdit de toute manière dans les requêtes préparée (comme USE par exemple)

moi ce code passe très bien et regarde il est un peu complexe... 2 curseurs imbriqué et (oh miracle) un select interne!!!
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
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
-- uniquement pour le test
DROP DATABASE IF EXISTS hotels;
CREATE DATABASE hotels DEFAULT character SET utf8 collate utf8_general_ci;
-- on sélectionne la bd quoi qu'il arrive pour bien travailler avec elle par défaut
USE hotels; -- à toi d'adapter
 
-- on définit les table et on les remplit uniquement pour le test
CREATE TABLE hotel(
	id		int(4) NOT NULL AUTO_INCREMENT,
	nom	varchar(255) NOT NULL,
	constraint pk_hotel PRIMARY KEY(id)
)engine=myisam AUTO_INCREMENT=1;
CREATE TABLE personne(
	id		int(4) NOT NULL AUTO_INCREMENT,
	nom	varchar(255) NOT NULL,
	constraint pk_personne PRIMARY KEY(id)
)engine=myisam AUTO_INCREMENT=1;
-- la table de liaison, je ne mets pas de contrainte dessus car je la crée avec le moteur myisam qui ne s'en occupe pas
CREATE TABLE personne_a_dormi(
	id				int(4) NOT NULL AUTO_INCREMENT,
	idPersonne 	int(4) NOT NULL,
	idHotel		int(4) NOT NULL,
	constraint pk_personne_a_dormi PRIMARY KEY(id)
)engine=myisam AUTO_INCREMENT=1;
 
INSERT INTO hotel(nom)VALUES("hotel1"),("hotel2"),("hotel3");
INSERT INTO personne(nom)VALUES("personne1"),("personne2"),("personne3"),("personne4");
INSERT INTO personne_a_dormi(idPersonne,idHotel)VALUES(1,1),(1,2),(2,2),(3,1),(3,3),(4,1),(4,2),(4,3);
 
-- on définit la procédure stockée
DROP procedure IF EXISTS recapitulatif;
delimiter |
CREATE procedure recapitulatif()
begin
	declare ligne text DEFAULT "personne";
	declare tmp varchar(255);
	declare done,test bool;
	declare cpers,chotel int(4);
	declare colonnes cursor FOR SELECT nom FROM hotel;
	declare lignes cursor FOR SELECT id,nom FROM personne;
	declare lithotel cursor FOR SELECT id FROM hotel;
	declare CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
	-- on crée l'entête
	open colonnes;
	SET done=false;
	repeat
		fetch colonnes INTO tmp;
		IF NOT done then
			SET ligne=concat(ligne,",",tmp);
		end IF;
	until done end repeat;
	close colonnes;
	SELECT ligne AS entete;
	SET done=false;
	open lignes;
	repeat
		fetch lignes INTO cpers,tmp;
		IF NOT done then
			SET test=done;
			SET ligne=tmp;
			open lithotel;
			repeat
				fetch lithotel INTO chotel;
				IF NOT done then
					SELECT IF(count(id)>0,"Oui","Non") INTO tmp FROM personne_a_dormi WHERE idPersonne=cpers AND idHotel=chotel;
					SET ligne=concat(ligne,",",tmp);
				end IF;
			until done end repeat;
			close lithotel;
			SELECT ligne;
			SET done=test;
		end IF;
	until done end repeat;
	close lignes;
end|
delimiter ;
-- fin de la procédure stockée
 
-- on teste en appelant la procédure
call recapitulatif();

Après c'est soit la configuration soit la version de mysql ou du connecteur mysql dans ton langage interrogateur qui est pas à jour
ericd69 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 17h11.


 
 
 
 
Partenaires

Hébergement Web