Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

Given an array of ids $galleries = array(1,2,5) I want to have a SQL query that uses the values of the array in its WHERE clause like:

SELECT *
FROM galleries
WHERE id = /* values of array $galleries... eg. (1 || 2 || 5) */

How can I generate this query string to use with MySQL?

share|improve this question

This question has an open bounty worth +200 reputation from HamZa ending in 3 days.

One or more of the answers is exemplary and worthy of an additional bounty.

Levi Morrison's answer needs some attention...

    
3  
@trante this one is the oldest (2009). –  Fabián Sep 13 '13 at 17:33
    
Is there any similar solution for problem like SELECT * FROM TABLE WHERE NAME LIKE ( 'ABC%' or 'ABD%' OR .. ) –  Eugine Joseph Jun 12 '14 at 7:11
    
Please consider selecting another answer as right. –  Daniel yesterday

13 Answers 13

up vote 228 down vote accepted

BEWARE! This answer contains a severe SQL Injection vulnerability. Do NOT use the code samples presented here. This answer is only preserved to prevent breaking links and for reference value.

$ids = join(',',$galleries);  
$sql = "SELECT * FROM galleries WHERE id IN ($ids)";
share|improve this answer
2  
The identifiers are still a quoted list, so it comes out as "WHERE id IN ( '1,2,3,4' )", for example. You need to quote each identifier separately, or else ditch the quotes inside the parentheses. –  Rob May 25 '09 at 20:05
9  
I just add the warning that $galleries should be input validated before this statement! Prepared statements can't handle arrays AFAIK, so if you are used to bound variables, you could easily make SQL injection possible here. –  leemes Mar 27 '12 at 11:07
5  
This answer should be edited to make it less harmful to anyone who copy/pastes it. @FlaviusStef, do you think you could edit to address the blatant SQL injection risks here? –  Chris Baker May 15 '14 at 2:34
10  
PLEASE DON'T USE THIS ANSWER!!! Use the CW by "Your Common Sense". –  Hans Jun 5 '14 at 23:23
4  
Dangerous answer is dangerous. As mentioned, SQL injection vulnerabilities are potentially rampant here. –  Dan Lugg Aug 28 '14 at 16:03

In SQL the IN() operator checks if a value exists in a given set.

The PHP code below uses prepared statements for MySQLi or PDO to help mitigate SQL injection attacks. The variable $ids is an array that is assumed to contain at least one value. Error checking is omitted for brevity; you need to check for the usual errors for each database method (or set your DB driver to throw exceptions).

$in = join(',', array_fill(0, count($ids), '?'));

$select = <<<SQL
    SELECT *
    FROM galleries
    WHERE id IN ($in);
SQL;


// if using MySQLi (PHP 5.6):
$statement = $mysqli->prepare($select);
$statement->bind_param(str_repeat('i', count($ids)), ...$ids);
$statement->execute();
$result = $statement->get_result();

// if using PDO (or don't have PHP 5.6):
$statement = $pdo->prepare($select);
$statement->execute($ids);

Using the IN() operator with strings.

It is easy to change between strings and integers because of the bound parameters. For PDO there is no change required; for MySQLi change str_repeat('i', to str_repeat('s', if you need to check strings.

share|improve this answer
    
What does ...$ids do? I get "syntax error, unexpected '.'". –  Marcel Sep 18 '14 at 0:43
    
I see them, I am using MySQLi and I have php 5.6 –  Marcel Sep 18 '14 at 15:52
1  
This answer should be accepted instead. –  marcio Apr 9 at 20:50

ints:

$query = "SELECT * FROM `$table` WHERE `$column` IN(".implode(',',$array).")";

strings:

$query = "SELECT * FROM `$table` WHERE `$column` IN('".implode("','",$array)."')";
share|improve this answer
1  
Why '\' ??Please tell me –  zloctb Sep 20 '13 at 11:42

How can I create a prepared statement for IN () operator?

Prepared statement can represent complete data literal only. Not a part of literal, nor a complex expression, nor identifier. But either string or number only. So, a very common pitfall is a query like this:

$ids = array(1,2,3);
$stm = $pdo->prepare("SELECT * FROM t WHERE id IN (?)");
$stm->execute(array($ids));

it will actually bind a word 'Array' and raise a warning.

One have to create a query with placeholders representing every array member, and then bind this array values for execution:

$ids = array(1,2,3);
$stm = $pdo->prepare("SELECT * FROM t WHERE id IN (?,?,?)");
$stm->execute($ids);

To make this query more flexible, it's better to create a string with ?s dynamically:

$ids = array(1,2,3);
$in  = str_repeat('?,', count($arr) - 1) . '?';
$sql = "SELECT * FROM table WHERE column IN ($in)";
$stm = $db->prepare($sql);
$stm->execute($ids);
$data = $stm->fetchAll();

Of course, if we have other variables to be bound, we need to add them to values array:

$ids = array(1,2,3);
$in  = str_repeat('?,', count($arr) - 1) . '?';
$sql = "SELECT * FROM table WHERE column IN ($in) AND category=?";
$stm = $db->prepare($sql);
$ids[] = $category; //adding another member to array
$stm->execute($ids);
$data = $stm->fetchAll();

the code become quite bloated but that's all PDO can offer to handle such complex cases. As a further improvement one can invent their own placeholders to support such complex data types.

share|improve this answer
    
You also have to handle the case of an empty array separately as MySQL doesn't allow the empty list as in field IN (). How about writing a function for this which applies PDO::quote to each value in the set? –  Adder May 14 '13 at 14:46
    
Yup, you are right. However, I have a better idea already and I hope I will come up with neat solution pretty soon :) –  Your Common Sense May 14 '13 at 14:59
    
Isn't this better? join(',', array_fill(0, count($arr), '?')) :) –  deceze Jun 12 '13 at 8:44

Assuming you properly sanitize your inputs beforehand...

$matches = implode(',', $galleries);

Then just adjust your query:

SELECT *
FROM galleries
WHERE id IN ( $matches )

Quote values appropriately depending on your dataset.

share|improve this answer
    
Yea, yours is better than mine was :P –  Aiden Bell May 25 '09 at 19:39
select id from galleries where id in (1, 2, 5);

Simple for each loop will work.

EDIT: Flavius/AvatarKava's way is better, but make sure that none of the array values contain commas.

share|improve this answer

Besides using IN query you have two options to do so as In query there is a risk of SQL Injection vulnerability you can use looping to get the exact data you want or you can use the query with OR case


    1. SELECT *
          FROM galleries WHERE id=1 or id=2 or id=5;


    2. $ids = array(1, 2, 5);
       foreach ($ids as $id) {
          $data[] = SELECT *
                        FROM galleries WHERE id= $id;
       }

share|improve this answer

Because the original question relates to an array of numbers and I am using an array of strings I couldnt make the given examples work.

I found that each string needed to be encapsulated in single quotes to work with the IN() function.

Here is my solution

foreach($status as $status_a) {
        $status_sql[] = '\''.$status_a.'\'';
    }
    $status = implode(',',$status_sql);

$sql = mysql_query("SELECT * FROM table WHERE id IN ($status)");

As you can see the first function wraps each array variable in single quotes (\') and then implodes the array.

NOTE: $status does not have single quotes in the SQL statement.

There is probably a nicer way to add the quotes but this works.

share|improve this answer
    
Or $filter = "'" . implode("','",$status) . "'"; –  Alejandro Salamanca Mazuelo 11 hours ago

You may have table texts (T_ID (int), T_TEXT (text)) and table test (id (int), var (varchar(255)))

in insert into test values (1, '1,2,3') ;

the following will output rows from table texts where T_ID IN (1,2,3)

SELECT * FROM `texts` WHERE (SELECT FIND_IN_SET( T_ID, ( SELECT var FROM test WHERE id =1 ) ) AS tm) >0

this way you can manage a simple n2m db relation without extra table and using only SQL without need to us PHP or other programming lang.

share|improve this answer

As @Flavius Stef, you can use intval() to make sure all id is int values.

$ids = join(',', array_map('intval', $galleries));  
$sql = "SELECT * FROM galleries WHERE id IN ($ids)";
share|improve this answer
$ids = "(".implode(',',$galleries).")";  // you can remplace "implode" with "join"  
$sql = "SELECT * FROM galleries WHERE id IN $ids";
share|improve this answer
    
This query also has the potential of adding sql injection. –  Cristik 2 hours ago

you can generate the queries by

$galleries = array(1,2,5);

$sql = "SELECT * FROM gallery WHERE id IN (". 
           implode(', ', 
                     array_map(function(&$item){ 
                                   return "'".$item."'";
                               }, $galleries)) 
        .");";

using array_map to add a single quote to each of elements in the $galleries. the generated $sql var will be :

SELECT * FROM gallery WHERE id IN ('1', '2', '5');

share|improve this answer

Safer.

$galleries = array(1,2,5);
array_walk($galleries , 'intval');
$ids = implode(',', $galleries);
$sql = "SELECT * FROM galleries WHERE id IN ($ids)";
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.