问题
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?
回答1:
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.
回答2:
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.
回答3:
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 iii
$bindString = str_repeat('i', count($ids));
$stmt = $mysqli->prepare('SELECT * FROM somewhere WHERE `id` IN (' . $bindClause . ') ORDER BY `name`;');
$stmt->bind_params($bindString, ...$ids);
$stmt->execute();
回答4:
I'll add an ultimately 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(
idINT );
INSERT INTO
idsVALUES(?);
this will insert your IDsSELECT
idFROM
idsLEFT JOIN .... ;
use data from other tables to sort theids
listSELECT
idFROM
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.
回答5:
An alternative would be to use PHP usort function on the result object, but this is "manual."
See this: Sort Object in PHP
回答6:
No, it's not recommended, if you are to fetch certain records from the database using ORDER BY
clause.
回答7:
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.
来源:https://stackoverflow.com/questions/3703180/a-prepared-statement-where-in-query-and-sorting-with-mysql