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

Modérateur PHPfrance
Modérateur PHPfrance | 6373 Messages

02 juin 2005, 17:16

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;

ViPHP
ViPHP | 1380 Messages

02 juin 2005, 17:50

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;
ripat

Eléphant du PHP | 125 Messages

11 juil. 2005, 12:07

je vais essayer de depatouiller tout ca si ja mais a cet apres midi :wink:
petit ou grand l'important c'est la référence

Eléphant du PHP | 217 Messages

12 juil. 2005, 08:49

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.

Administrateur PHPfrance
Administrateur PHPfrance | 3131 Messages

12 juil. 2005, 10:04

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.

Modérateur PHPfrance
Modérateur PHPfrance | 6373 Messages

12 juil. 2005, 10:05

c'est possible d'avoir un petit exemple ? :oops:

Administrateur PHPfrance
Administrateur PHPfrance | 3131 Messages

12 juil. 2005, 10:07

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).')';

Eléphanteau du PHP | 29 Messages

23 juil. 2005, 14:32

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]

Modérateur PHPfrance
Modérateur PHPfrance | 6373 Messages

23 juil. 2005, 14:37

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%)