Related
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?
Locked. Comments on this answer have been disabled, but it is still accepting other interactions. Learn more.
BEWARE! This answer contains a severe SQL injection vulnerability. Do NOT use the code samples as presented here, without making sure that any external input is sanitized.
$ids = join("','",$galleries);
$sql = "SELECT * FROM galleries WHERE id IN ('$ids')";
Using PDO:[1]
$in = join(',', array_fill(0, count($ids), '?'));
$select = <<<SQL
SELECT *
FROM galleries
WHERE id IN ($in);
SQL;
$statement = $pdo->prepare($select);
$statement->execute($ids);
Using MySQLi [2]
$in = join(',', array_fill(0, count($ids), '?'));
$select = <<<SQL
SELECT *
FROM galleries
WHERE id IN ($in);
SQL;
$statement = $mysqli->prepare($select);
$statement->bind_param(str_repeat('i', count($ids)), ...$ids);
$statement->execute();
$result = $statement->get_result();
Explanation:
Use the SQL IN() operator to check if a value exists in a given list.
In general it looks like this:
expr IN (value,...)
We can build an expression to place inside the () from our array. Note that there must be at least one value inside the parenthesis or MySQL will return an error; this equates to making sure that our input array has at least one value. To help prevent against SQL injection attacks, first generate a ? for each input item to create a parameterized query. Here I assume that the array containing your ids is called $ids:
$in = join(',', array_fill(0, count($ids), '?'));
$select = <<<SQL
SELECT *
FROM galleries
WHERE id IN ($in);
SQL;
Given an input array of three items $select will look like:
SELECT *
FROM galleries
WHERE id IN (?, ?, ?)
Again note that there is a ? for each item in the input array. Then we'll use PDO or MySQLi to prepare and execute the query as noted above.
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.
[1]: I've omitted some error checking for brevity. You need to check for the usual errors for each database method (or set your DB driver to throw exceptions).
[2]: Requires PHP 5.6 or higher. Again I've omitted some error checking for brevity.
ints:
$query = "SELECT * FROM `$table` WHERE `$column` IN(".implode(',',$array).")";
strings:
$query = "SELECT * FROM `$table` WHERE `$column` IN('".implode("','",$array)."')";
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.
Use:
select id from galleries where id in (1, 2, 5);
A simple for each loop will work.
Flavius/AvatarKava's way is better, but make sure that none of the array values contain commas.
As Flavius Stef's answer, you can use intval() to make sure all id are int values:
$ids = join(',', array_map('intval', $galleries));
$sql = "SELECT * FROM galleries WHERE id IN ($ids)";
For MySQLi with an 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 statement:
$qmarks = implode(',', array_fill(0, count($ids), '?'));
$sth = $dbh->prepare("SELECT * FROM galleries WHERE id IN ($qmarks)");
$sth->execute($ids);
We should take care of SQL injection vulnerabilities and an empty condition. I am going to handle both as below.
For a pure numeric array, use the 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 a function would most likely be already available to you in your application, or maybe you've already created one.
Sanitize the string array like:
$values = array_map('escape', $gallaries);
A 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 sometimes, like $galleries = array(); we should therefore note that IN () does not allow for an empty list. One can also use OR instead, but the 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 an empty array instead of hiding all rows, simply replace 0 with 1 in the ternary's false part.
Safe way without PDO:
$ids = array_filter(array_unique(array_map('intval', (array)$ids)));
if ($ids) {
$query = 'SELECT * FROM `galleries` WHERE `id` IN ('.implode(',', $ids).');';
}
(array)$ids Cast $ids variable to array
array_map Transform all array values into integers
array_unique Remove repeated values
array_filter Remove zero values
implode Join all values to IN selection
Safer.
$galleries = array(1,2,5);
array_walk($galleries , 'intval');
$ids = implode(',', $galleries);
$sql = "SELECT * FROM galleries WHERE id IN ($ids)";
Col. Shrapnel's SafeMySQL library for PHP provides type-hinted placeholders in its parametrised queries, and includes a couple of convenient placeholders for working with arrays. The ?a placeholder expands out an array to a comma-separated list of escaped strings*.
For example:
$someArray = [1, 2, 5];
$galleries = $db->getAll("SELECT * FROM galleries WHERE id IN (?a)", $someArray);
* Note that since MySQL performs automatic type coercion, it doesn't matter that SafeMySQL will convert the ids above to strings - you'll still get the correct result.
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:
$galleryIds = implode(',', $galleries);
I.e. now you should safely use $query = "SELECT * FROM galleries WHERE id IN ({$galleryIds})";
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 database relation without an extra table and using only SQL without the need to use PHP or some other programming language.
More an example:
$galleryIds = [1, '2', 'Vitruvian Man'];
$ids = array_filter($galleryIds, function($n){return (is_numeric($n));});
$ids = implode(', ', $ids);
$sql = "SELECT * FROM galleries WHERE id IN ({$ids})";
// output: 'SELECT * FROM galleries WHERE id IN (1, 2)'
$statement = $pdo->prepare($sql);
$statement->execute();
Besides using the IN query, you have two options to do so as in an IN query there is a risk of an 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;
}
Because the original question relates to an array of numbers and I am using an array of strings I couldn't 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.
Below is the method I have used, using PDO with named placeholders for other data. To overcome SQL injection I am filtering the array to accept only the values that are integers and rejecting all others.
$owner_id = 123;
$galleries = array(1,2,5,'abc');
$good_galleries = array_filter($chapter_arr, 'is_numeric');
$sql = "SELECT * FROM galleries WHERE owner=:OWNER_ID AND id IN ($good_galleries)";
$stmt = $dbh->prepare($sql);
$stmt->execute(array(
"OWNER_ID" => $owner_id,
));
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
I'm using PDO method in my PHP page to implode two strings (in order to create a graph... long story!), but I don't know how to filter them. The table structure in MySQL is like this:
Column Name:
item (the name of the item being voted on);
nvote (the number of votes this item has received);
date (the dates of the votes)
This is what I have so far:
$stmt1 = $db->prepare("SELECT date FROM vote");
$stmt1->execute();
$stmt2 = $db->prepare("SELECT nvote FROM vote");
$stmt2->execute();
$line1 = implode( ',', $stmt1->fetchAll (PDO::FETCH_COLUMN) );
$line2 = implode( ',', $stmt2->fetchAll (PDO::FETCH_COLUMN) );
(Line1 creates the x-axis of my graph, line2 creates the y-axis)
This works very well to generate the strings for my graph.
How can I filter these so that name of the item being voted on (in the "item" column") is filtered by a var (in this case, $nameofitem)? I can't seem to get it to work.
$params = array(':value' => 'Hello World');
$stmt1 = $db->prepare("SELECT date FROM vote WHERE item = :value ORDER BY date");
$stmt1->execute($params);
$stmt2 = $db->prepare("SELECT nvote FROM vote WHERE item = :value ORDER BY date");
$stmt2->execute($params);
$line1 = implode( ',', $stmt1->fetchAll (PDO::FETCH_COLUMN) );
$line2 = implode( ',', $stmt2->fetchAll (PDO::FETCH_COLUMN) );
The key is adding a WHERE condition in the SQL query with a parameter that is bound by execute when passed an array.
Note that I also added an order statement for you as there is no guarantee of the result ordering without it, meaning the points you saw on the graph could have been associated with the wrong point. Date might not be the best choice, use a unique key if you can. Alternatively, you could fetch everything in a single query and build your lists with post-processing.
I have written a php script that returns an arbitrary number of specific ids (which are in the format of numbers) in an array. I would like to make a new query that selects each row from a table that belongs to each id. I know i can do 1 query to get one row with the matching id. But i would like to do this all in one query. Here is my code:
$id = array(1,4,7,3,11,120); // The array containing the ids
$query = mysql_query("SELECT *
FROM posts
WHERE id = '$id[0]'");
// I would like to Do this for each id in the array and return it as one group of rows.`
I think you want the IN clause:
$idList = implode(",", $id);
SELECT *
FROM posts
WHERE id IN ( $idList );
The implode() function will turn your array of numbers into a comma-separated string of those same values. When you use it as part of an IN clause, it tells the database to use those values as a lookup table to match id against.
Standard Disclaimer/Warning:
As with any SQL query, you really shouldn't be directly concatenating variables into the query string. You're just opening yourself up to SQL injection. Use prepared/parameterized statements instead.
Use PHP's implode function to convert the array into a comma separated value string.
Then, you can use the SQL IN clause to run a single SQL statement containing the values associated with the ids you captured from PHP:
$id = array(1,4,7,3,11,120);
$csv = implode(',', $id);
$query = sprintf("SELECT *
FROM posts
WHERE id IN (%s)",
mysql_real_escape_string($csv));
$result = mysql_query($query)
I omitted the single quotes because they aren't necessary when dealing with numeric values in SQL. If the id values were strings, each would have to be encapsulated inside of single quotes.
What you want is SQL's IN clause.
SELECT * FROM posts WHERE id IN (1, 4, 7, 11, 120)
In PHP, you'll probably want something like:
$query = mysql_query(sprintf("SELECT * FROM posts WHERE id IN (%s)", implode(',', $id)));
Obviously, that's assuming you know you have integer values for $id, and that the values for $id didn't come from the user (that is, they should be sanitized). To be safe, you really ought to do something like:
$ids = implode(',', array_map('mysql_real_escape_string', $id));
$query = mysql_query("SELECT * FROM posts WHERE id IN ($ids)");
And if $id is dynamically generated, don't forget to put something in that IN clause, because SELECT * FROM foo WHERE bar IN () will give you an error. I generally make sure to set my IN-clause variables to 0, since IN (0) is good, and primary keys are pretty much never 0.
This question already has answers here:
How can I bind an array of strings with a mysqli prepared statement?
(7 answers)
Closed 10 months ago.
Imagine we have a query:
SELECT * FROM somewhere WHERE `id` IN(1,5,18,25) ORDER BY `name`;
and an array of IDs to fetch: $ids = array(1,5,18,25)
With prepared statements it's adviced to prepare one statement and call it multiple times:
$stmt = $mysqli->prepare('SELECT * FROM somewhere WHERE `id`=?;');
foreach ($ids as $id){
$stmt->bind_params('i', $id);
$stmt->exec();
}
But now I'll have to sort the results manually. Do I have any nice alternatives?
you could do it this way:
$ids = array(1,5,18,25);
// creates a string containing ?,?,?
$clause = implode(',', array_fill(0, count($ids), '?'));
$stmt = $mysqli->prepare('SELECT * FROM somewhere WHERE `id` IN (' . $clause . ') ORDER BY `name`;');
call_user_func_array(array($stmt, 'bind_param'), $ids);
$stmt->execute();
// loop through results
Using this you're calling bind_param for each id and you have sorting done by mysql.
Had the same problem and in addition to the answer of #sled 7 years ago, here is a possibility without making the call_user_func_array(array($stmt, 'bind_param'), $ids); step, but only call bind_params once:
$ids = array(1,5,18,25);
// creates a string containing ?,?,?
$bindClause = implode(',', array_fill(0, count($ids), '?'));
//create a string for the bind param just containing the right amount of s
$bindString = str_repeat('s', count($ids));
$stmt = $mysqli->prepare('SELECT * FROM somewhere WHERE `id` IN (' . $bindClause . ') ORDER BY `name`;');
$stmt->bind_param($bindString, ...$ids);
$stmt->execute();
I believe this is the simplest possible answer :
$ids = [1,2,3,4,5];
$pdos = $pdo->prepare("SELECT * FROM somwhere WHERE id IN (:"
. implode(',:', array_keys($ids)) . ") ORDER BY id");
foreach ($ids as $k => $id) {
$pdos->bindValue(":". $k, $id);
}
$pdos->execute();
$results = $pdos->fetchAll();
So long your array of Ids does not contain keys or keys with illegal characters, it wil work.
For the task of executing a secure mysqli query with a dynamic number of incoming values to be fed into the sql string, a prepared statement is the professional technique to implement.
Let's assume that the incoming data payload is user-supplied data -- this means that we cannot guarantee the integrity of the data nor can we guarantee the volume of data. In fact, the expected array of data might be empty. The below snippet will demonstrate how to pass an array of ids to the IN () condition in the WHERE clause of a prepared statement. If there are no values in the array, then a prepared statement provides no benefit and should not be used.
MySQLi result set objects can be immediately iterated by a foreach() loop. Therefore, it is not necessary to make iterated fetch calls; just access the rows' data using array syntax.
The array of ids means that the sql will expect integer values. When calling bind_param(), the first parameter will be a single string of repeated i characters. For general use, if the data will be strings or you might have a mix of data types (e.g. integers, floats/doubles, or strings), then is simpler to just use repeated s characters instead of i characters.
Code: (PHPize.online Demo with SQL)
$ids = [1, 5, 18, 25]; // this could be, for example: $_GET['ids']
$count = count($ids);
$sql = 'SELECT name FROM somewhere';
$orderBy = 'ORDER BY name';
if ($count) {
$placeholders = implode(',', array_fill(0, $count, '?'));
$stmt = $mysqli->prepare("$sql WHERE id IN ($placeholders) $orderBy");
$stmt->bind_param(str_repeat('i', $count), ...$ids);
$stmt->execute();
$result = $stmt->get_result();
} else {
$result = $mysqli->query("$sql $orderBy"); // a prepared statement is unnecessary
}
foreach ($result as $row) {
echo "<div>{$row['name']}</div>\n";
}
Output from my PHPize demo:
<div>Alan</div>
<div>Bill</div>
<div>Chad</div>
<div>Dave</div>
If you don't need to iterate the result set for any reason, then you can fetch_all(). This is commonly used when immediately echoing or returning a json-encoded string (say, as the response to an ajax call). In this case, you replace the foreach() block with: (PHPize.online Demo with SQL)
echo json_encode($result->fetch_all(MYSQLI_ASSOC));
or simply dump the multidimensional array:
var_export($result->fetch_all(MYSQLI_ASSOC));
Output from my PHPize demo:
[{"name":"Alan"},{"name":"Bill"},{"name":"Chad"},{"name":"Dave"}]
From PHP8.1 and higher, it is no longer necessary to call bind_param() because the execute() method can receive the payload of parameters as an array (like PDO).
This means that...
$stmt->bind_param(str_repeat('i', $count), ...$ids);
$stmt->execute();
can be replaced with...
$stmt->execute($ids);
Here's a complete, basic example: (PHPize.online Demo)
$ids = [1, 2, 3, 4, 5];
$stmt = $mysqli->prepare("SELECT * FROM somewhere WHERE id IN (" . rtrim(str_repeat('?,', count($ids)), ',') . ") ORDER BY id");
$stmt->execute($ids);
var_export($stmt->get_result()->fetch_all(MYSQLI_ASSOC));
Topical Resources:
php.net
The RFC was authored by our very own Dharman ♦ and implemented as part of PHP8.1 after a unanimous vote on 2021-03-27.
phpbackend.com article from 24, October 2021
Reddit thread
PDO can do this concisely.
I'll add a slow & ugly solution which nevertheless uses prepared statements for ANY number of array items :) 3 statements are universal for any case and can be reused everywhere.
CREATE TEMPORARY TABLE `ids`( `id` INT );
INSERT INTO `ids` VALUES(?); this will insert your IDs
SELECT `id` FROM `ids` LEFT JOIN .... ; use data from other tables to sort the ids list
SELECT `id` FROM `ids`; select everything back
Otherwise you'll have to use IN (?,?,?,.... or sort the rows manually. The best idea is to use simple MySQL-queries, or, try to get the list of IDs already sorted in the way you like.
Have you considered rewriting you original query using a JOIN and WHERE clause to get the IDS you need to avoid the need for a WHERE IN clause? I came here with the same question and after reviewing the possible solutions I realized an INNER JOIN was my solution.
Copied from my answer here How to use PDO prepared statements with IN clause?
using named place holders
$values = array(":val1"=>"value1", ":val2"=>"value2", ":val2"=>"$value3");
$statement = 'SELECT * FROM <table> WHERE `column` in(:'.implode(', :',array_keys($values)).') ORDER BY `column`';
using ??
$values = array("value1", "value2", "$value3");
$statement = 'SELECT * FROM <table> WHERE `column` in('.trim(str_repeat(', ?', count($values)), ', ').') ORDER BY `column`';
An alternative would be to use PHP usort function on the result object, but this is "manual."
See this:
Sort Object in PHP
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?
Locked. Comments on this answer have been disabled, but it is still accepting other interactions. Learn more.
BEWARE! This answer contains a severe SQL injection vulnerability. Do NOT use the code samples as presented here, without making sure that any external input is sanitized.
$ids = join("','",$galleries);
$sql = "SELECT * FROM galleries WHERE id IN ('$ids')";
Using PDO:[1]
$in = join(',', array_fill(0, count($ids), '?'));
$select = <<<SQL
SELECT *
FROM galleries
WHERE id IN ($in);
SQL;
$statement = $pdo->prepare($select);
$statement->execute($ids);
Using MySQLi [2]
$in = join(',', array_fill(0, count($ids), '?'));
$select = <<<SQL
SELECT *
FROM galleries
WHERE id IN ($in);
SQL;
$statement = $mysqli->prepare($select);
$statement->bind_param(str_repeat('i', count($ids)), ...$ids);
$statement->execute();
$result = $statement->get_result();
Explanation:
Use the SQL IN() operator to check if a value exists in a given list.
In general it looks like this:
expr IN (value,...)
We can build an expression to place inside the () from our array. Note that there must be at least one value inside the parenthesis or MySQL will return an error; this equates to making sure that our input array has at least one value. To help prevent against SQL injection attacks, first generate a ? for each input item to create a parameterized query. Here I assume that the array containing your ids is called $ids:
$in = join(',', array_fill(0, count($ids), '?'));
$select = <<<SQL
SELECT *
FROM galleries
WHERE id IN ($in);
SQL;
Given an input array of three items $select will look like:
SELECT *
FROM galleries
WHERE id IN (?, ?, ?)
Again note that there is a ? for each item in the input array. Then we'll use PDO or MySQLi to prepare and execute the query as noted above.
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.
[1]: I've omitted some error checking for brevity. You need to check for the usual errors for each database method (or set your DB driver to throw exceptions).
[2]: Requires PHP 5.6 or higher. Again I've omitted some error checking for brevity.
ints:
$query = "SELECT * FROM `$table` WHERE `$column` IN(".implode(',',$array).")";
strings:
$query = "SELECT * FROM `$table` WHERE `$column` IN('".implode("','",$array)."')";
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.
Use:
select id from galleries where id in (1, 2, 5);
A simple for each loop will work.
Flavius/AvatarKava's way is better, but make sure that none of the array values contain commas.
As Flavius Stef's answer, you can use intval() to make sure all id are int values:
$ids = join(',', array_map('intval', $galleries));
$sql = "SELECT * FROM galleries WHERE id IN ($ids)";
For MySQLi with an 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 statement:
$qmarks = implode(',', array_fill(0, count($ids), '?'));
$sth = $dbh->prepare("SELECT * FROM galleries WHERE id IN ($qmarks)");
$sth->execute($ids);
We should take care of SQL injection vulnerabilities and an empty condition. I am going to handle both as below.
For a pure numeric array, use the 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 a function would most likely be already available to you in your application, or maybe you've already created one.
Sanitize the string array like:
$values = array_map('escape', $gallaries);
A 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 sometimes, like $galleries = array(); we should therefore note that IN () does not allow for an empty list. One can also use OR instead, but the 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 an empty array instead of hiding all rows, simply replace 0 with 1 in the ternary's false part.
Safe way without PDO:
$ids = array_filter(array_unique(array_map('intval', (array)$ids)));
if ($ids) {
$query = 'SELECT * FROM `galleries` WHERE `id` IN ('.implode(',', $ids).');';
}
(array)$ids Cast $ids variable to array
array_map Transform all array values into integers
array_unique Remove repeated values
array_filter Remove zero values
implode Join all values to IN selection
Safer.
$galleries = array(1,2,5);
array_walk($galleries , 'intval');
$ids = implode(',', $galleries);
$sql = "SELECT * FROM galleries WHERE id IN ($ids)";
Col. Shrapnel's SafeMySQL library for PHP provides type-hinted placeholders in its parametrised queries, and includes a couple of convenient placeholders for working with arrays. The ?a placeholder expands out an array to a comma-separated list of escaped strings*.
For example:
$someArray = [1, 2, 5];
$galleries = $db->getAll("SELECT * FROM galleries WHERE id IN (?a)", $someArray);
* Note that since MySQL performs automatic type coercion, it doesn't matter that SafeMySQL will convert the ids above to strings - you'll still get the correct result.
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:
$galleryIds = implode(',', $galleries);
I.e. now you should safely use $query = "SELECT * FROM galleries WHERE id IN ({$galleryIds})";
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 database relation without an extra table and using only SQL without the need to use PHP or some other programming language.
More an example:
$galleryIds = [1, '2', 'Vitruvian Man'];
$ids = array_filter($galleryIds, function($n){return (is_numeric($n));});
$ids = implode(', ', $ids);
$sql = "SELECT * FROM galleries WHERE id IN ({$ids})";
// output: 'SELECT * FROM galleries WHERE id IN (1, 2)'
$statement = $pdo->prepare($sql);
$statement->execute();
Besides using the IN query, you have two options to do so as in an IN query there is a risk of an 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;
}
Because the original question relates to an array of numbers and I am using an array of strings I couldn't 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.
Below is the method I have used, using PDO with named placeholders for other data. To overcome SQL injection I am filtering the array to accept only the values that are integers and rejecting all others.
$owner_id = 123;
$galleries = array(1,2,5,'abc');
$good_galleries = array_filter($chapter_arr, 'is_numeric');
$sql = "SELECT * FROM galleries WHERE owner=:OWNER_ID AND id IN ($good_galleries)";
$stmt = $dbh->prepare($sql);
$stmt->execute(array(
"OWNER_ID" => $owner_id,
));
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);