2012-05-07 3 views
8
$ids = array(1,2,3); 
$in = implode(',',$ids); 

$query = "SELECT * FROM user where user_id IN ($in) "; 

La requête fonctionne sans problème. Mais quand $ids est un tableau vide $ids = array();Comment gérer une requête SQL IN vide?

J'ai une erreur de requête sql juste parce que SELECT * FROM user where user_id IN() n'est pas une requête valide.

Comment puis-je éviter une telle situation sans vérifier la présence d'une matrice vide, c'est-à-dire faire fonctionner la requête, quoi qu'il arrive?

+0

Pourquoi ne pas vérifier uniquement la matrice vide? MySQL attend juste certains paramètres après IN, donc je suppose qu'il n'y a aucun moyen –

+2

J'espère que $ ids ne sont pas fournis par l'utilisateur et si, vous les échappez correctement, avant de les insérer dans votre requête. – knittl

+0

J'ai une situation où je ne peux pas vérifier le tableau vide. Je devais faire courir la requête sans erreur. Tout ce que je peux faire est de changer le paramètre d'entrée. Les requêtes lancées retournent le résultat zéro est ok pour moi. –

Répondre

6

La meilleure façon de gérer c'est:

$in = implode("','",$ids); // generate like 1','2 
$query = "SELECT * FROM user where user_id IN ('$in') "; // if has 1','2 surrond it with quote make it IN('1','2') and if empty than IN('') 

Cela vous évite d'if/else structure et tout le reste

+1

Dans certains cas, la colonne pourrait contenir une valeur vide, et cette solution renverra toutes les valeurs vides. Cela peut arriver dans une colonne de clé étrangère, par exemple. – NLemay

+1

Si user_id est un identifiant unique, il génère une erreur de conversion. – Gqqnbig

+0

Bien que ce soit évidemment une solution intelligente, c'est déroutant et pas vraiment intuitif. Vous devez comprendre beaucoup pour lire ceci. L'anser de @ faizan-ali est meilleur à cet égard. –

5

vous pouvez ajouter 0 en avance sur la chaîne $ ids. Après tout, aucun ID ne démarrera à partir de 0 dans une base de données.

Ou vous pouvez faire comme ça ..

$sql = "SELECT * FROM user where ".($ids != ''? "user_id IN ($ids)" : " 1=1"); 
7

vous ne devriez pas exécuter la requête lorsque le $ en est vide. Je pense que ce yoou besoin est quelque chose comme ça

$in = implode(',',$ids); 
if($in) { 
    $query = "SELECT * FROM user where user_id IN ($in) "; 
} 
else { 
     //alternate scenario here 
} 

Modifier

$in = implode("','",$ids); // generate like 1','2 
$query = "SELECT * FROM user where user_id IN ('$in') "; // if has 1','2 surrond it with quote make it IN('1','2') and if empty than IN('') 
+1

Comment savez-vous que la requête ne devrait pas être exécutée sans condition si '$ ids' est vide? Aussi, injection SQL? – Jon

+0

car si $ in est vide, le sql va lancer une exception comme expliqué dans la question –

+0

Je n'ai pas demandé pourquoi il * ne sera pas * exécuté, mais pourquoi * il ne devrait pas être exécuté. Comment savez-vous que le PO ne veut pas sélectionner tous les utilisateurs dans ce cas? – Jon

-1

Vous devez définir une concaténation conditionnelle:

if (count($ids) > 0) 
{ 
    $in = implode(',',$ids); 
    $query = "SELECT * FROM user WHERE user_id IN ($in)"; 
    // .... 
} 

EDIT: fixe mon incompréhension.

-1

Pour la requête donnée, vous ne devriez pas l'exécuter du tout.

if ($ids) { 
    // run your code 
} else { 
    return false; //or whatever. 
} 

pour les autres cas, il pourrait être concaténation conditionnelle comme indiqué dans les autres réponses

0
if((count($in)>0) 
{ 
    //execute sql query code 
} 
0

Je fais plusieurs types de vérification dans différentes situations pour faire e Assurez-vous que l'instruction sql est valide. Dans le type le plus fondamental de la vérification, je fais en sorte que la variable ne soit pas vide ou faux

$in = implode(',',$ids); 
if(!$ids) $in="0"; 
$query = "SELECT * FROM user WHERE user_id IN ($ids)"; 

En général, j'utilise toute une série de db_* fonctions qui valident l'entrée je passe dans les requêtes afin que je puisse gérer utilisations plus avancées vérifier où le tableau $ids vient de

Voici un code de test qui fonctionne bien pour moi dans des dizaines de situations.

function db_number_list($lst) 
{ 
    if(!$lst) 
     return "0"; // if there are no passed in values , return a 0 
    if (!is_array($lst)) 
     $lst = explode (",",$lst); //if a lst was passed in, create an array 
    foreach ($lst as $k=>$val) 
    { 
     if(!is_numeric(trim($val))) 
      unset($lst[$k]);//remove non-numeric values; 
    } 
    if(!count($lst)) 
     return "0"; //if nothing is in the array after removing non-numeric values, return 0 
    return implode (",",$lst); 
} 

$ids=array(); 
$query = "SELECT * FROM user WHERE user_id IN (".db_number_list($ids).")"; 
echo "ids:'".print_r($ids,true)."'<br>$query<hr>"; 

$ids="1,2,45,6,"; 
$query = "SELECT * FROM user WHERE user_id IN (".db_number_list($ids).")"; 
echo "ids:'".print_r($ids,true)."'<br>$query<hr>"; 

$ids=array(3,6,1,"drop table x", 4); 
$query = "SELECT * FROM user WHERE user_id IN (".db_number_list($ids).")"; 
echo "ids:'".print_r($ids,true)."'<br>$query<hr>"; 

Sortie:

ids:'Array () ' 
SELECT * FROM user WHERE user_id IN (0) 

ids:'1,2,45,6,' 
SELECT * FROM user WHERE user_id IN (1,2,45,6) 

ids:'Array ([0] => 3 [1] => 6 [2] => 1 [3] => drop table x [4] => 4) ' 
SELECT * FROM user WHERE user_id IN (3,6,1,4) 

4

ajouter habituellement toujours une valeur "invalide", la liste est jamais vide:

$in = implode(',', array_merge($ids, [-1])); // never empty! 

Aucune instruction conditionnelle supplémentaire n'est requise, ce qui permet de garder le code relativement propre. La valeur "invalide" doit être en dehors de la plage des valeurs autorisées, bien sûr. (L'exemple ci-dessus suppose que les valeurs $ids valides sont toujours positives.)

+1

Honnêtement, c'est la meilleure solution. – Davor