Based on Can I bind an array to an IN() condition?
The above question doesn't have any answers for using multiple WHERE clauses.
The second best answer works only with one WHERE clause:
$qMarks = str_repeat('?,', count($ids) - 1) . '?';
$sth = $db->prepare("SELECT * FROM myTable WHERE id IN ($qMarks)");
$sth->execute($ids);
If I put an additional WHERE clause, it produces an empty result or error.
$qMarks = str_repeat('?,', count($ids) - 1) . '?';
$sth = $db->prepare("SELECT * FROM myTable WHERE id IN ($qMarks) AND locationid=?");
$sth->execute(array($ids, ?)); // Also tried $sth->execute($ids, $location_id) and $sth->execute($ids, array($location_id));
Please advise.
execute accepts a single array of parameters. You need to do:
$sth->execute(array_merge($ids, [$location_id]));
Related
This question already has answers here:
Can I bind an array to an IN() condition in a PDO query?
(23 answers)
Closed 1 year ago.
I'm reworking some PHP code to use PDO for the database access, but I'm running into a problem with a "WHERE... IN" query.
I'm trying to delete some things from a database, based on which items on a form are checked. The length and content of the list will vary, but for this example, imagine that it's this:
$idlist = '260,201,221,216,217,169,210,212,213';
Then the query looks like this:
$query = "DELETE from `foo` WHERE `id` IN (:idlist)";
$st = $db->prepare($query);
$st->execute(array(':idlist' => $idlist));
When I do this, only the first ID is deleted. (I assume it throws out the comma and everything after it.)
I've also tried making $idlist an array, but then it doesn't delete anything.
What's the proper way to use a list of items in a PDO prepared statement?
Since you can't mix Values (the Numbers) with control flow logic (the commas) with prepared statements you need one placeholder per Value.
$idlist = array('260','201','221','216','217','169','210','212','213');
$questionmarks = str_repeat("?,", count($idlist)-1) . "?";
$stmt = $dbh->prepare("DELETE FROM `foo` WHERE `id` IN ($questionmarks)");
and loop to bind the parameters.
This may be helpful too:
https://phpdelusions.net/pdo#in
$arr = [1,2,3];
$in = str_repeat('?,', count($arr) - 1) . '?';
$sql = "SELECT * FROM table WHERE column IN ($in)";
$stm = $db->prepare($sql);
$stm->execute($arr);
$data = $stm->fetchAll();
I would make $idlist and array, then simply loop through the array using foreach to delete the specific item.
$idlist = array('260','201','221','216','217','169','210','212','213');
$stmt = $dbh->prepare("DELETE FROM `foo` WHERE `id` = ?");
$stmt->bindParam(1, $id);
foreach ($idlist as $item){
$id = $item;
$stmt->execute();
}
I can successfully implement a IN clause within a PDO prepared statement using the following code.
in_array = array(1,2,3);
$in = str_repeat('?,', count($in_array) - 1) . '?';
$sql = "SELECT * FROM my_table WHERE my_value IN ($in)";
$stm = $db->prepare($sql);
$stm->execute($in_array);
$data = $stm->fetchAll();
How can I do the same for multiple $in? For example I've unsuccessfully tried the following:
in_array1 = array(1,2,3);
$in1 = str_repeat('?,', count($in_array) - 1) . '?';
in_array2 = array(4,5,1);
$in2 = str_repeat('?,', count($in_array) - 1) . '?';
$sql = "SELECT * FROM my_table WHERE (my_value1 IN ($in1)) AND (my_value2 IN ($in2))";
$stm = $db->prepare($sql);
$stm->execute($in_array1,$in_array2);
$data = $stm->fetchAll();
I think its got to do with stm->execute but not sure, help appreciated
Your current query comes out as
SELECT * FROM my_table WHERE (my_value1 IN (?,?,?)) AND (my_value2 IN (?,?,?))
So your execute usage is incorrect, http://php.net/manual/en/pdostatement.execute.php. It should only be passing one array with values inside it.
An array of values with as many elements as there are bound parameters in the SQL statement being executed. All values are treated as PDO::PARAM_STR.
I think using array_merge, http://php.net/manual/en/function.array-merge.php, will allow you to accomplish what you are trying
$stm->execute(array_merge($in_array1,$in_array2));
This way the execute is the equivalent of
$stm->execute(array(1,2,3,4,5,1));
This may seem incorrect because the array pairings are now gone but placeholder 1 (the first question mark) will map to 1, placeholder 4 to 4, and so on.
Doesn't make sense.
Look at this:
$query = $db->prepare("SELECT * FROM table WHERE value1 = ? AND value2 = ?");
$query ->execute(array($value1, $value2));
and this:
http://php.net/manual/en/pdo.prepare.php
I am using the following PDO query:
<?php
$cadena = $_SESSION[Region];
// We Will prepare SQL Query
$STM = $dbh->prepare("SELECT `id_mesero`, `nombre_mesero`,`alias_mesero`, `rest_mesero` FROM tbmeseros WHERE cadena_mesero='$cadena'");
// For Executing prepared statement we will use below function
$STM->execute();
// we will fetch records like this and use foreach loop to show multiple Results
$STMrecords = $STM->fetchAll();
foreach($STMrecords as $row)
{
The value from the 'rest_mesero' field is the index from the table 'tbrestaurantes'.
I would need to join some fields values from 'tbrestaurantes' to the PDO query, but I don't know how to do it using PDO.
Any help is welcome.
UPDATED QUESTION TEXT
This is my proposal for the query :
$dbh->prepare("SELECT * FROM tbmeseros LEFT JOIN tbrestaurantes ON tbmeseros.rest_mesero = tbrestaurantes.id_restaurante WHERE tbmeseros.cad_mesero = ?");
But is show an error:
Warning: PDOStatement::execute() [pdostatement.execute]: SQLSTATE[HY093]: Invalid parameter number: no parameters were bound in /.../AdminMeseros.php on line 80
Line 80 is
$STM->execute();
This is my updated query:
<?php
$cadena = $_SESSION[Region];
$STM =$dbh->prepare("SELECT * FROM tbmeseros LEFT JOIN tbrestaurantes ON tbmeseros.rest_mesero = tbrestaurantes.id_restaurante WHERE tbmeseros.cad_mesero = ?");
$STM->bindParam(1, $cadena);
// For Executing prepared statement we will use below function
$STM->execute(array($cadena));
// we will fetch records like this and use foreach loop to show multiple Results
$STMrecords = $STM->fetchAll();
foreach($STMrecords as $row)
{
And here table's screenshots:
For tbmeseros:
For tbrestaurantes:
The value of $cadena is 'HQ3'.
When you put a parameter in the SQL, you need to supply the value for the parameter. There are two ways to do that:
1) Call bindParam():
$STM->bindParam(1, $cadana);
2) Provide the values when calling execute():
$STM->execute(array($cadana));
You need to fill the ? in the query:
$q = $dbh->prepare("SELECT * FROM tbmeseros LEFT JOIN tbrestaurantes ON tbmeseros.rest_mesero = tbrestaurantes.id_restaurante WHERE tbmeseros.cad_mesero = ?");
$q->bindValue( 1, 'x' );
$q->execute();
print_r( $q->fetchAll( PDO::FETCH_ASSOC );
In prepare you can use '?' and then bindValue to attach an escaped value to the query. Your query doesn't appear to have this and that is the cause of the error.
following query returns all wanted results if entered in phpmyadmin:
SELECT postid, voting
FROM postvotes
WHERE userid = 1
AND postid IN
(1007,1011,1012,1013,1014,
1015,1016,1017,1018,1019,1020,1021,1023,1025,1026,
1027,1028,1029,1030,1031)
But PDO fails to fetchAll(). It just returns the first match like fetch().
What's wrong?
PHP Code:
private function userPostVotings( $postIDs ) {
// $postIDs contains a string like 1,2,3,4,5,6,7...
// generated through implode(',', idArray)
try {
$userPostVote = $this->_db->prepare('SELECT postid, voting
FROM postvotes
WHERE userid = ?
AND postid IN ( ? )');
$userPostVote->setFetchMode(\PDO::FETCH_ASSOC);
$userPostVote->execute( array( $this->_requester['id'], $postIDs ) );
while ( $res = $userPostVote->fetch() ) {
var_dump( $res );
}
} catch (\PDOException $p) {}
}
If I echo out the query used in this method and fire it through phpmyadmin I get the correct number of results. However PDO gives just the first. No matter if a loop with fetch() or fetchAll().
You cannot bind array in prepared statements in PDO.
Reference:
Can I bind an array to an IN() condition?
it is not PDO's fetchAll() of course, but your query.
Which is not
IN (1007,1011,1012,1013,1014)
but
IN ('1007,1011,1012,1013,1014')
and of course it will find only first value as this string will be cast to the first number
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();
I am using php mysql-pdo and symfony
issue is : I have a query as stated below
WHERE STATUS IN (:STATUS)
with value of status as A','B.
and when i bind this as sting its escaping as below
WHERE STATUS IN ('A\',\'B')
and hence wrong output.
pleass help
Prepared statement can represent a complete data literal only. Not a part of literal, nor a complex expression, nor identifier. But either string or number only. Thus, your query doesn't work as you are actually binding a complex expression, not because of quotes
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.