Nombre variables de params dans une requete SQL
Le
Marc Nadeau
J'ai un script qui interroge une BD mysql (banal) et qui parfois ne doit
tenir compte que d'un champs de recherche, parfois doit faire une recherche
plus serrée en sélectionnant sur 2 ou 3 champs.
Actuellement, je dois faire effectuer la requête par des fonctions
différentes selons le nombre de champs utilisés.
--
# fonction1: un seul critère:
snip
my ($critere, $clef) = @_;
snip
$sth = $dbh->prepare ("SELECT COUNT(*) FROM bannieres WHERE $critere LIKE
\"$clef\" ");
snip
-
# fonction2: 2 critères
my ($critere01, $clef01, $critere02, $clef02) = @_;
$sth = $dbh->prepare ("SELECT COUNT(*) FROM bannieres WHERE $critere01 LIKE
\"$clef01\" AND $critere02 LIKE \"$clef02\" ");
--
# fonction3: Ainsi de suite
Je voudrais faire exécuter toutes ces requêtes par une seule et même
fonction qui créerait une requête différente selon le nombre de paramètres
envoyés à la dite fonction.
Ce n'est pas critique pcq le programme fonctionne bien, mais je veux éviter
la redondance dans le code.
Merci d'avance!
--
L'Amiral nous brouille l'écoute avec sa panne de micro
tenir compte que d'un champs de recherche, parfois doit faire une recherche
plus serrée en sélectionnant sur 2 ou 3 champs.
Actuellement, je dois faire effectuer la requête par des fonctions
différentes selons le nombre de champs utilisés.
--
# fonction1: un seul critère:
snip
my ($critere, $clef) = @_;
snip
$sth = $dbh->prepare ("SELECT COUNT(*) FROM bannieres WHERE $critere LIKE
\"$clef\" ");
snip
-
# fonction2: 2 critères
my ($critere01, $clef01, $critere02, $clef02) = @_;
$sth = $dbh->prepare ("SELECT COUNT(*) FROM bannieres WHERE $critere01 LIKE
\"$clef01\" AND $critere02 LIKE \"$clef02\" ");
--
# fonction3: Ainsi de suite
Je voudrais faire exécuter toutes ces requêtes par une seule et même
fonction qui créerait une requête différente selon le nombre de paramètres
envoyés à la dite fonction.
Ce n'est pas critique pcq le programme fonctionne bien, mais je veux éviter
la redondance dans le code.
Merci d'avance!
--
L'Amiral nous brouille l'écoute avec sa panne de micro

Poser une question


--8<--
#!/usr/bin/perl
use strict;
use warnings;
print requete(
'A' => '1',
'B' => '2',
'C' => '3',
'D' => '4',
);
sub requete {
my %parms = @_;
my $requete = "SELECT COUNT(*) FROM bannieres WHERE ";
my @criteres_like;
foreach (keys %parms) {
push @criteres_like, "$_ LIKE $parms{$_}";
}
$requete .= join(" AND ", @criteres_like);
return $requete;
}
-->8--
SELECT COUNT(*) FROM bannieres WHERE A LIKE 1 AND D LIKE 4 AND C LIKE 3
AND B LIKE 2
Note: l'utilisation d'un hash fait que l'ordre des critères passés en
paramètre n'est pas conservé. Mais c'est tellement plus simple/élégant
avec un hash :)
# Tu répupère les parametres dans un hash.
my %criteres = @_;
# Le WHERE TRUE fonctionne avec PostgreSQL. Avec MySQL, je crois me
# rappeler que la syntaxe est différente (WHERE 1, il me semble).
# L'important est d'avoir une première condition toujours vraie
# simplement pour pouvoir empiler les AND derrière.
my $sql = 'SELECT COUNT(*) FROM bannieres WHERE TRUE ';
# On crée les conditions de la clause WHERE
for ( keys %criteres ) {
$sql .= ' AND $_ LIKE ' . $criteres{$_} ;
}
# Et voila :-)
$sth = $dbh->prepare($sql);
__END__
Voila, à tester, adapter selon tes besoins, mais le principe est là. Il
faut caculer ta chaine SQL dynamiquement.
Ah bah oui, c'est encore mieux comme ça tiens :)
"map" est tout indiqué dans ce cas là :
my @criteres_like = map { "$_ LIKE $parms{$_}" } keys %parms;
splice ? ou shift ? quelque chose comme ceci (non testé) :
my $query;
my $first = 1;
my $critere;
my $clef;
while (@_) {
...
($critere, $clef) = splice(@_, 0, 2);
<ou encore>
$critere = shift; $clef = shift;
</ou encore>
...
if (first) {
$query = "SELECT COUNT(*) FROM bannieres WHERE $critere LIKE "$clef";
} else {
$query .= " AND $critere LIKE "$clef";
}
...
$first = 0;
}
$sth = $dbh->prepare ($query);
Jean-Pierre