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 7 hours.

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
1  
Please consider selecting another answer as right. –  Daniel Apr 13 at 6:33

20 Answers 20

up vote 220 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
3  
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
10  
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
2  
This answer should be accepted instead. –  marcio Apr 9 at 20:50

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
1  
Isn't this better? join(',', array_fill(0, count($arr), '?')) :) –  deceze Jun 12 '13 at 8:44

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

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

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 2 days 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

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

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

For mysqli with escape function:

$ids = array_map(function($a) use($mysqli) { 
    return is_string($a) ? "'".$mysqli->real_escape_string($a)."'" : $a;
  }, $ids);
$ids = join(',', $ids);  
$result = $mysqli->query("SELECT * FROM galleries WHERE id IN ($ids)");

for PDO with prepared statesment:

$qmarks = array_implode(',', array_fill(0, count($ids), '?'));
$sth = $dbh->prepare("SELECT * FROM galleries WHERE id IN ($qmarks)");
$sth->execute($ids);
share|improve this answer
$ids = join(',',$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 days 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

You can use "implode" or "join" for array to string

    $ids = implode(',',$galleries);  
    $sql = "SELECT * FROM galleries WHERE id IN ($ids)";

mysql_query($sql);
share|improve this answer

We can use this "WHERE id IN" clause if we filter the input array properly. Something like this:

$galleries = array();

foreach ($_REQUEST['gallery_id'] as $key => $val) {
    $galleries[$key] = filter_var($val, FILTER_SANITIZE_NUMBER_INT);
}

Like the example below:enter image description here

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

I.e. now you should safely use $query = "SELECT * FROM galleries WHERE id IN ({$galleryIds})";

share|improve this answer

use mysql IN function

$galleries = array(1,2,5);
$galleriesClause = implode(",",$galleries);

SELECT *
FROM galleries
WHERE id IN ($galleriesClause)
share|improve this answer

We should take care of SQL injection vulnerabilities and empty condition. I am going to handle both as below.

For pure numeric array use appropriate type conversion viz intval or floatval or doubleval over each element. For string types mysqli_real_escape_string() which may also be applied to numeric values if you wish. MySQL allows numbers as well as date variants as string.

To appropriately escape the values before passing to the query create a function similar to:

function escape($string)
{
    // Assuming $db is a link identifier returned by mysqli_connect() or mysqli_init()
    return mysqli_real_escape_string($db, $string);
}

Such function would most likely be already available to you in your application, or may be you've already created one.

Sanitize string array like:

$values = array_map('escape', $gallaries);

Numeric array can be sanitized using intval or floatval or doubleval instead as suitable:

$values = array_map('intval', $gallaries);

Then finally build the query condition

$where  = count($values) ? "`id` = '" . implode("' OR `id` = '", $values) . "'" : 0;

or

$where  = count($values) ? "`id` IN ('" . implode("', '", $values) . "')" : 0;

Since the array can also be empty soemtimes, like $galleries = array(); therefore we should note that IN () does not allow for an empty list. One can also use OR instead but problem remains. So the above check count($values) is to ensure the same.

And add it to the final query:

$query  = 'SELECT * FROM `galleries` WHERE ' . $where;

TIP: If you want to show all records (no filtering) in case of empty array instead of hiding all rows, simply replace 0 with 1 in the ternary's false part.

share|improve this answer

Please check this

<?php
    $connection = mysql_connect("hostname","username","password");

    if (!$connection) {
    die('PHP Mysql database connection could not connect : ' . mysql_error());
    }
    else{ 
    $db_name = "db_name";
    $array1 = array(1,5,7);
    $str = implode(',',$array1);

    mysql_select_db($db_name, $connection);

     $sql = "select * from galleries where gallery_id IN ($str)";

    $records = mysql_query($sql, $connection); 
    while($rows = mysql_fetch_array($records))
      {
        echo "Gallery Id : " . $rows['gallery_id'] . "<br />";
        echo "Gallery Name : " . $rows['gallery_name'] . "<br />";
      }
    }
    mysql_close($connection); 
    ?> 
share|improve this answer
    
With the ' in ('.$str.') it won't work –  DocRattie 57 mins ago

Your Answer

 
discard

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