OVH Cloud OVH Cloud

Formuler une requête à partir d'éléments d'une hashtable

6 réponses
Avatar
Gibier Jean-Charles
Salut,
je souhaite passer une hastable à une fonction utilisant DBI pour faire une
requête SQL de type insert into XXX (AAA,BBB,CCC) VALUES (DDD,EEE,FFF).
La hastable en question contient logiquement les nom des champs en clé
(AAA,BBB,CCC) et le contenu des champs dans les valeurs (DDD,EEE,FFF).
Comment faire pour construire la requête plus élégamment qu'avec une
concaténation dans un foreach ?
Ou existe t'il une fonction de DBI pour cela ?

Merci.
JCG

6 réponses

Avatar
Paul GABORIT
À (at) Wed, 16 Jun 2004 22:21:27 +0200,
"Gibier Jean-Charles" écrivait (wrote):
je souhaite passer une hastable à une fonction utilisant DBI pour faire une
requête SQL de type insert into XXX (AAA,BBB,CCC) VALUES (DDD,EEE,FFF).
La hastable en question contient logiquement les nom des champs en clé
(AAA,BBB,CCC) et le contenu des champs dans les valeurs (DDD,EEE,FFF).
Comment faire pour construire la requête plus élégamment qu'avec une
concaténation dans un foreach ?


En supposant que votre table de hachage s'appelle %h et en décomposant la
construction dans un souci pédagogique :


my $champs = join(',', keys %h);
my $place_holder = join(',', '?' x scalar(keys %h);
my @valeurs = values %h;

my $sth = $dbh->prepare("insert into XXX ($champs) values ($place_holder)");
my $rv = $sth->execute(@valeurs);

Ou existe t'il une fonction de DBI pour cela ?


Je n'ai pas vu une telle chose.

--
Paul Gaborit - <http://www.enstimac.fr/~gaborit/>
Perl en français - <http://www.enstimac.fr/Perl/>

Avatar
Gibier Jean-Charles
"Paul GABORIT" a écrit dans le message news:


Merci, je ne pensais pas avoir la réponse ce soir !
Je vais me pencher sur cette notion de place_holder, ceci dit ...

my $place_holder = join(',', '?' x scalar(keys %h);


Ne manque t'il pas une parenthèse ? (que j'imagine être à la fin mais sait
on jamais ...)
Et le 'x' signifie t'il bien un x ? (c'est neuneu comme question mais
d'instinct j'aurais plutôt mis un '*')

Avatar
Paul GABORIT
À (at) Thu, 17 Jun 2004 00:02:10 +0200,
"Gibier Jean-Charles" écrivait (wrote):
"Paul GABORIT" a écrit dans le message news:


Merci, je ne pensais pas avoir la réponse ce soir !

my $place_holder = join(',', '?' x scalar(keys %h);


Ne manque t'il pas une parenthèse ? (que j'imagine être à la fin mais sait
on jamais ...)


Vous avez tout à fait raison. Une erreur de frappe (je n'ai pas testé ce bout
de code).

Et le 'x' signifie t'il bien un x ? (c'est neuneu comme question mais
d'instinct j'aurais plutôt mis un '*')


Non, C'est bien un 'x'. C'est l'opérateur de multiplication de chaînes ou de
liste. Et une deuxième erreur, une ! Tel que je l'ai utilisé, il multiplie la
chaîne alors qu'il faut multiplier une liste.

Donc au final, cette fameuse ligne doit être :

my $place_holder = join(',', ('?') x scalar(keys %h));

(Et là, j'ai testé ;-)

Je vais me pencher sur cette notion de place_holder, ceci dit ...


L'usage des place_holder est quasi-indispensable pour insérer sans problème
des valeurs quelconques dans votre base. Par exemple, des valeurs contenant
des apostrophes ('), des guillemets (") ou des barres obliques inverses ().

--
Paul Gaborit - <http://www.enstimac.fr/~gaborit/>
Perl en français - <http://www.enstimac.fr/Perl/>


Avatar
Laurent Wacrenier
Paul GABORIT écrit:

my $sth = $dbh->prepare("insert into XXX ($champs) values ($place_holder)");
my $rv = $sth->execute(@valeurs);


Pour un INSERT, on peut écrire :

$rv = $dbh->do("insert into XXX ($champs) values ($place_holder)", undef, @valuers);

Ou existe t'il une fonction de DBI pour cela ?


Je n'ai pas vu une telle chose.


Les paresseux doivent utiliser d'autres modules pour cela.


Avatar
Gibier Jean-Charles
"Paul GABORIT" a écrit dans le message news:


À (at) Thu, 17 Jun 2004 00:02:10 +0200,
"Gibier Jean-Charles" écrivait (wrote):
"Paul GABORIT" a écrit dans le message
news:








[...]
Je vais me pencher sur cette notion de place_holder, ceci dit ...


L'usage des place_holder est quasi-indispensable pour insérer sans
problème

des valeurs quelconques dans votre base. Par exemple, des valeurs
contenant

des apostrophes ('), des guillemets (") ou des barres obliques inverses
().




Bien que risquant un renvoi immédiat au HS ou au perldoc j'ose une autre
question :
Dans un phase de débugage comment est il possible de récupérer la syntaxe
effective de la requête passée avec cette méthode ?
Explication : J'utilise mysql et les champs de type date ne semblent pas
accepter la fonction NOW() passée en tant que valeur alors qu'avec la
méthode traditionnelle d'insertion cela fonctionnait bien. Je voudrais donc
bien savoir ce que reçoit la base. Je pose la question de chez moi et je me
rends compte qu'au boulot j'aurai pu regarder les logs de mysql. Ceci dit
il n'est pas sûr que j'y trouve la solution alors s'il y a une recette ...
Merci.

JCG


Avatar
Paul GABORIT
À (at) Thu, 17 Jun 2004 23:49:40 +0200,
"Gibier Jean-Charles" écrivait (wrote):
"Paul GABORIT" a écrit dans le message news:

L'usage des place_holder est quasi-indispensable pour insérer sans problème
des valeurs quelconques dans votre base. Par exemple, des valeurs contenant
des apostrophes ('), des guillemets (") ou des barres obliques inverses
().

Dans un phase de débugage comment est il possible de récupérer la syntaxe

effective de la requête passée avec cette méthode ?


En lisant 'perldoc DBI', on voit qu'il existe une méthode 'trace'.

Explication : J'utilise mysql et les champs de type date ne semblent pas
accepter la fonction NOW() passée en tant que valeur alors qu'avec la
méthode traditionnelle d'insertion cela fonctionnait bien.


NOW() est transformé en 'NOW()' ce qui évite son interprétation en tant que
fonction. C'est le but des place_holder : insérer les valeurs littéralement
sans aucune interprétation. Problème : 'NOW()' n'est pas une valeur acceptable
pour une date. Si vous voulez vraiment que NOW() soit interprété par le SGBD,
il ne faut pas utilisez les place_holder pour cette valeur.

En plus illustratif :

INSERT INTO XXX(Date) VALUES(NOW())

n'a pas le même le sens que :

INSERT INTO XXX(Date) VALUES('NOW()')



--
Paul Gaborit - <http://www.enstimac.fr/~gaborit/>
Perl en français - <http://www.enstimac.fr/Perl/>