Page 1 sur 1

Requête SQL dynamique avec paramètres variables et nombreux

Posté : 02 juin 2005, 17:16
par ouckileou
Si l'on veut créer une requête dynamiquement, par exemple en fonction de critères issus d'un formulaire
1 ou 2 paramètres possibles passent encore, plus cela fait beaucoup de combinaisons à tester

La solution est donc de tester chaque paramètre indépendamment des autres et de rajouter ou non la clause correspondante dans la requête

Le problème maintenant est de savoir si c'est le premier critère choisi (et donc s'il faut mettre un "WHERE") ou un des suivants (et mettre un "AND")

la solution est d'expédier le WHERE avec une clause toujours vrai du genre "1 = 1" et ensuite de n'ajouter que des AND
si on n'ajoute aucune clause, on récupérera bien tous les enregistrements puisque 1 est toujours égal à 1

un petit exemple :
// j'ai un formulaire qui permet de choisir 0, 1, 2 ou 3 critères de sélection
$param1 = (isset($_GET['param1']))?$_GET['param1']:null;
$param2 = (isset($_GET['param2']))?$_GET['param2']:null;
$param3 = (isset($_GET['param3']))?$_GET['param3']:null;

// je crée le code SQL de base de la requête avec un WHERE toujours vrai
$requete = "SELECT champ1, champ2 FROM table WHERE 1 = 1";

// et ensuite, je vais rajouter ou non des critères de sélection à ma requête suivant les paramètres
// sans me soucier de savoir si chacun est le premier à être utilisé
if (!empty($param1)) {
	$requete .= " AND champ3 = '".$param1."'";
}

if (!empty($param2)) {
	$requete .= " AND champ4 = '".$param2."'";
}

if (!empty($param3)) {
	$requete .= " AND champ5 = '".$param3."'";
}

// on peut vérifier, la requête est construite et correcte
echo $requete;

Posté : 02 juin 2005, 17:50
par Ripat
Astucieux!

Une variante pour les loooooongues listes de conditions:
$param[0] = 'condition 1';
$param[1] = 'condition 2';
$param[2] = 'condition 3';


$requete = 'SELECT champ1, champ2 FROM table';

// teste si il y a des conditions à mettre
if (!empty($param)){
  $where = ' WHERE ';
  // boucle sur les conditions. Pas de AND pour la dernière.
  $comptage = count($param);
  foreach ($param as $k=>$v){
    $and = ($k < $comptage - 1) ? ' AND ' : null;
    $where .= $v.$and;
  }
}

echo $requete.$where;

Posté : 11 juil. 2005, 12:07
par batti2b
je vais essayer de depatouiller tout ca si ja mais a cet apres midi :wink:

Posté : 12 juil. 2005, 08:49
par mojorisin
Personnelement j'utilise une autre solution :
pour chaque paramètre de clause je construis la clause et la mets dans un tableau (array_push). Une fois les paramètre traités, si le tableau n'est pas vide je fais un join avec la chaine ' AND ' ou ' OR ' puis applique cela à la suite du WHERE.

Posté : 12 juil. 2005, 10:04
par naholyr
Personnelement j'utilise une autre solution :
pour chaque paramètre de clause je construis la clause et la mets dans un tableau (array_push). Une fois les paramètre traités, si le tableau n'est pas vide je fais un join avec la chaine ' AND ' ou ' OR ' puis applique cela à la suite du WHERE.
C'est cette technique que j'utilise. Elle a le mérite d'être utilisable dans tous les cas de figure :

Code : Tout sélectionner

SELECT * FORM tb WHERE champ IN (val1,val2,val3,...,valn)

Code : Tout sélectionner

SELECT champ1,champ2,champ3,...,champn FROM tb WHERE ...
etc...

Avec un test sur la taille du tableau avant de créer la requête pour insérer la bonne valeur en cas de vide.

Posté : 12 juil. 2005, 10:05
par ouckileou
c'est possible d'avoir un petit exemple ? :oops:

Posté : 12 juil. 2005, 10:07
par naholyr
Pour reprendre l'exemple de Ripat
$param[0] = 'condition 1';
$param[1] = 'condition 2';
$param[2] = 'condition 3';


$requete = 'SELECT champ1, champ2 FROM table';

// teste si il y a des conditions à mettre
if (!empty($param)) {
  $where = ' WHERE '.join(' AND ',$param);
}

echo $requete.$where;
Si on a des OR dans les condition, il vaut mieux parenthéser pour être sûr de soi:
$where = ' WHERE ('.join(') AND (',$param).')';

Posté : 23 juil. 2005, 14:32
par airbem
BONJOUR

Et lorque l'on a une requete de type

SELECT * FROM quotes_table MATCH (quote) AGAINST ('"mang馱uot; "pens馱uot;' IN BOOLEAN MODE) and champ5=$champ and champ6=$champ6.

J'ai essayer de faire sa en suivant l'exemple de "ouckileou" mais sa ne marche pas:

$recherche = $_POST['recherche'];
$niveau=$_POST['niveau']; 
$ann_exp=$_POST['ann_exp'];
$fonction=$_POST['fonction']; 
$mobil=$_POST['mobil'];



$requete = "SELECT * 
FROM cv WHERE 1 = 1"; 


if (!empty($recherche)) { 
    $requete .= " MATCH (
ref, titre, nom, code, ville, fonction, region1, nom_entr1, prec_ent, nom_entr2
)
AGAINST (
'$recherche'
IN BOOLEAN
MODE 
)"; 
} 

if (!empty($niveau)) { 
    $requete .= " AND niveau = '".$niveau."'"; 
} 

if (!empty($ann_exp)) { 
    $requete .= " AND ann_exp = '".$ann_exp."'"; 
} 

if (!empty($fonction)) { 
    $requete .= " AND fonction = '".$fonction."'"; 
} 

if (!empty($mobil)) { 
    $requete .= " AND mobil = '".$mobil."'"; 
} 
echo $requete; 
Je n'est aucun resultat
si ce n'est que la requete
  SELECT * FROM cv WHERE 1 = 1 MATCH ( ref, titre, nom, code, ville, fonction, region1, nom_entr1, prec_ent, nom_entr2 ) AGAINST ( 'duboi bac+2' IN BOOLEAN MODE )       
Quequ'un peut'il me dire ce qui ne va pas . Merci :oops: [/php]

Posté : 23 juil. 2005, 14:37
par ouckileou
ce post montrait juste des astuces pour construire facilement une requête

maintenant si tu as des problèmes avec la requête construite ce seraitp lutôt dans le forum "base de données"

est-ce qu'il y a une erreur MySQL ? je pense qu'il manque déjà un AND entre WHERE 1=1 et MATCH

est-ce que tu es sûr que tu dois avoir des résultats (en tenant compte de la règle des 50%)