PHP MySQL Prepared Query using IN - php

I have a couple of situations where I have an array of input, such as:
$myArray = array( "apple", "banana", "orange", "pear" );
Where the array could have any number of fruits in it. I want to use MySQL prepared statements in PHP to create a query similar to:
SELECT * FROM fruitcart WHERE fruitname IN ('apple','banana','orange','pear');
Previously, I was accomplishing this by doing something like:
$query = "SELECT * FROM fruitcart WHERE fruitname IN ('" . implode( "','", $myArray ) . "')";
but I'd like to know if there is a way I could do something similar with prepared statements?

There is no way to do that with a prepared statement. The only possibility is to do something like this:
$query = "SELECT * FROM fruitcart WHERE fruitname = ? OR fruitname = ? OR fruitname = ? ...
You can easily build a statement like this with an foreach loop.
But be aware that, since your array will probably have different amounts of values, this might cause some confusion in the database optimizer algorithms. For optimal performance you might want to prepare statements with for example 128, 64, 32, 16, 8, 4, 2, 1 slots and then use the biggest one you can fill until you got all your values from the database. That way the optimizer is able to deal with a much more limited amount of statement skeletons.
You can also use a temporary table for this. For example create a table that only contains the values (apple, banana, ...) and an id for your value set.
You can then insert the array of values into the database using a unique set-id (php offers a guid function for example) and then selecting them in a subquery:
$query = "SELECT * FROM fruitcart WHERE fruitname IN (SELECT fruitname FROM temptable WHERE setid = ?)"
That's easily preparable and will perform quite good.
You can use an in-memory table for the temptable so it will be very fast.

$placeholders = rtrim(str_repeat('?, ', count($myArray)), ', ') ;
$query = "SELECT * FROM fruitcart WHERE fruitname IN ($placeholders)";
$stm = $db->prepare($query) ;
$stm->execute($myArray) ;

You are using the proper way to do that, you can edit
$list = implode( ',', $myArray );
$query = "SELECT * FROM fruitcart WHERE fruitname IN ('" . $list . "')";
That's it :)

Related

mysql query does not work with where clause and variable [duplicate]

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

How to use php array with sql IN operator? [duplicate]

This question already has answers here:
Passing an array to a query using a WHERE clause
(17 answers)
Closed 11 months ago.
I have and array with two values and I want to use it with sql IN operator in select query.
Here is the structure of my table
id comp_id
1 2
2 3
3 1
I have an array $arr which have two values Array ( [0] => 1 [1] => 2 )
I want to fetch the record of comp_id 1 and comp_id 2. So I wrote the following query.
SELECT * from table Where comp_id IN ($arr)
But it does not return the results.
Since you have plain integers, you can simply join them with commas:
$sql = "SELECT * FROM table WHERE comp_id IN (" . implode(',', $arr) . ")";
If working with with strings, particularly untrusted input:
$sql = "SELECT * FROM table WHERE comp_id IN ('"
. implode("','", array_map('mysql_real_escape_string', $arr))
. "')";
Note this does not cope with values such as NULL (will be saved as empty string), and will add quotes blindly around numeric values, which does not work if using strict mysql mode.
mysql_real_escape_string is the function from the original mysql driver extension, if using a more recent driver like mysqli, use mysqli_real_escape_string instead.
However, if you just want to work with untrusted numbers, you can use intval or floatval to sanitise the input:
$sql = "SELECT * FROM table WHERE comp_id IN (" . implode(",", array_map('intval', $arr)) . ")";
you need to convert the array into comma-separated string:
$condition = implode(', ', $arr);
And, additionally, you might want to escape the values first (if you are unsure about the input):
$condition = implode(', ', array_map('mysql_real_escape_string', $arr));
$arr is a php array, to the sql server you need to send a string that will be parsed
you need to turn your array in a list like 1, 2, etc..
to do this you can use the function http://php.net/implode
so before running the query try
$arr = implode ( ', ', $arr);
You need to implode your array with ',' comma
$imploded_arr = implode(',', $arr);
SELECT * from table Where comp_id IN ($imploded_arr)
you can only pass string to mysql as query, so try this
mysql_query("SELECT * FROM table WHERE comp_id IN (".implode(',',$arr).")");
All the people here are proposing the same thing but i got a warning in WordPress because of a simple error. You need to add commas to your imploded string. To be precise something like this.
$query = "SELECT *FROM table Where comp_id IN ( '" . implode( "', '", $sanitized_brands ) . "' )";
Hoping it helps someone like me. :)
You're mixing PHP and SQL - for the IN SQL operator, you need a format like:
SELECT * from table WHERE comp_id IN (1,2)
So to get that in PHP you need to do something like:
$sql = "SELECT * from table Where comp_id IN (".implode(',',$arr).")"
Bear in mind that this only works if the array comprises of integers. You have to escape each element if they are strings.
You need something like:
$sql = "SELECT * from table where comp_id in (".implode(',',$arr.")";
You need to actually convert your $arr to a string. The simplest way with what you're doing would be to use implode()
$query = 'SELECT * from table Where comp_id IN (' . implode(',', $arr) . ')';
Right now if you echo your query you'll see that rather than the array being in the IN statement, it will just be the word "Array"
You need to convert the array to a string for use in the query:
$list = implode(',', $arr);
Then it can be used in the IN clause:
SELECT * from table Where comp_id IN ($list)
As per #barryhunter 's answer which works only on array that contains integer only:
$sql = "SELECT * from table Where comp_id IN (".implode(',',$arr).")";
I've made some tweaks to make it work for array of strings:
$sql = "SELECT * from table Where comp_id IN ('".implode("','",$arr)."')";
There are some risks of SQL injection in a few of the previous answers. It might be fine if you are completely certain about $arr being sanitized (and will stay that way). But if you aren't completely sure, you might want to mitigate such risk using $stmt->bindValue. Here is one way of doing it:
# PHP
$in_list = array();
for ($i = 0; $i < count($arr); $i++) {
$key = 'in_param_' . i;
$in_list[':' . $key] = array('id' => $arr[$i], 'param' => $key);
}
$keys = implode(', ', array_keys($in_list));
// Your SQL ...
$sql = "SELECT * FROM table where id IN ($keys)";
foreach ($in_list as $item) {
$stmt->bindValue($item['param'], $item['id'], PDO::PARAM_INT);
}
$stmt = $this->getConnection()->prepare($sql)->execute();
If your array is of Integers :
$searchStringVar = implode(",",$nameIntAryVar);
$query="SELECT * from table NameTbl WHERE idCol='$idVar' AND comp_id IN ($searchStringVar)";
If your array is of Strings :
$searchStringVar = implode("','",$nameStringAryVar);
$query="SELECT * from table NameTbl WHERE idCol='$idVar' AND comp_id IN ('$searchStringVar')";

How do you query using an "IN" WHERE clause with Zend_Db_Adapter_Mysqli::fetchAll()?

I'm having a strange problem with Zend_Db_Adapter_Mysqli. I need to query multiple items by ID from my database, so I have the following SQL,
SELECT * FROM mytable WHERE id IN (1,2,3)
This query works fine.
I then try and do this programatically with Zend_Db_Adapter_Mysqli,
$sql = 'SELECT * FROM mytable WHERE id IN (?)';
$ids = array(1,2,3);
$result = $adapter->fetchAll($sql, implode(',', $ids));
The problem is for the above PHP I only get back 1 result instead of the expected 3. I've tried just passing the $ids instead of using implode(), but I just get an error.
What am I doing wrong?
I'm not sure if it helps, but here's an answer on how to do it using Zend_Db_Select: How to create WHERE IN clause with Zend_Db_Select
EDIT:
Ok, if it really doesn't work, and you were planning on using a string anyway, can't you just do this:
$ids = array(1,2,3);
$sql = sprintf('SELECT * FROM mytable WHERE id IN (%s)', implode(',' $ids));
$result = $adapter->fetchAll($sql);
:)
Or, even more wonderful:
$ids = array(1,2,3);
$sql = sprintf('SELECT * FROM mytable WHERE id IN (%s)', implode(',' array_fill('?', count($ids)));
$result = $adapter->fetchAll($sql, $ids);
However, I'm not sure fetchAll would accept this.
Not so easy. See here:
http://forums.mysql.com/read.php?45,64588,66133#msg-66133
The fact that you get only one result is thanks to MySQL interpreting the string '1,2,3' as number 1. You will explicitly have to add three question marks to the query:
$ids = array(1,2,3);
$sql = 'SELECT * FROM mytable WHERE id IN (?, ?, ?)';
$result = $adapter->fetchAll($sql, $ids);
You can write a function that will transform $ids to the right number of question marks.
See this question/answer for a way to use the IN clause with a parameterized statement.
I have an array of integers, how do I use each one in a mysql query (in php)?

MySQL - How to select rows where value is in array?

Ok, normally I know you would do something like this if you knew the array values (1,2,3 in this case):
SELECT * WHERE id IN (1,2,3)
But I don't know the array value, I just know the value I want to find is 'stored' in the array:
SELECT * WHERE 3 IN (ids) // Where 'ids' is an array of values 1,2,3
Which doesn't work. Is there another way to do this?
Use the FIND_IN_SET function:
SELECT t.*
FROM YOUR_TABLE t
WHERE FIND_IN_SET(3, t.ids) > 0
By the time the query gets to SQL you have to have already expanded the list. The easy way of doing this, if you're using IDs from some internal, trusted data source, where you can be 100% certain they're integers (e.g., if you selected them from your database earlier) is this:
$sql = 'SELECT * WHERE id IN (' . implode(',', $ids) . ')';
If your data are coming from the user, though, you'll need to ensure you're getting only integer values, perhaps most easily like so:
$sql = 'SELECT * WHERE id IN (' . implode(',', array_map('intval', $ids)) . ')';
If the array element is not integer you can use something like below :
$skus = array('LDRES10','LDRES12','LDRES11'); //sample data
if(!empty($skus)){
$sql = "SELECT * FROM `products` WHERE `prodCode` IN ('" . implode("','", $skus) . "') "
}
If you use the FIND_IN_SET function:
FIND_IN_SET(a, columnname) yields all the records that have "a" in them, alone or with others
AND
FIND_IN_SET(columnname, a) yields only the records that have "a" in them alone, NOT the ones with the others
So if record1 is (a,b,c) and record2 is (a)
FIND_IN_SET(columnname, a) yields only record2 whereas FIND_IN_SET(a, columnname) yields both records.

Passing an array to a query using a WHERE clause

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

Categories