Using an IN in a where
I've been having some trouble using an IN in a where clause using MySQLi this is my query:
SELECT * FROM core_tags WHERE tag_id IN (1,2,3,4,5) GROUP BY tag_id ORDER BY tag_popularity ASC
If I run this in PHP My Admin then I get 5 results as I would expect. However if I run it in PHP with the following code I only get one result of the tag_id '1'.
Here's my PHP. Originally I was running it using functions in a class but I've hand coded it to test that it wasn't simply an error in my functions with the same prob开发者_如何学Clem.
$mysqli = new mysqli(DB_SERVER, DB_NAME, DB_PASSWORD, DB_NAME);
$rawQuery = 'SELECT * FROM core_tags WHERE tag_id IN (?) GROUP BY tag_id ORDER BY tag_popularity ASC';
$stmt = $mysqli->prepare($rawQuery);
$stmt->bind_param("s", $tag_ids);
$tag_ids = "1,2,3,4,5";
$stmt->execute();
$stmt->bind_result($tag_id, $tag_name, $tag_desc, $tag_popularity);
while ($stmt->fetch()) {
printf ("%s\n", $tag_name);
}
$stmt->close();
die();
Anyone have any idea why the mysqli version only returns one row? Using MySQL instead of mysqli works fine as well, same as PHP My Admin.
Using a string prepared statement will cause your final SQL to look like:
IN ('1,2,3,4,5')
with the quotes, which is not what you want. What I'd do is this:
$ids= array(1,2,3,4,5);
$mysqli = new mysqli(DB_SERVER, DB_NAME, DB_PASSWORD, DB_NAME);
$rawQuery = 'SELECT * FROM core_tags WHERE tag_id IN (';
$rawQuery .= implode(',',array_fill(0,count($ids),'?'));
$rawQuery .= ') GROUP BY tag_id ORDER BY tag_popularity ASC';
$stmt = $mysqli->prepare($rawQuery);
call_user_func_array(array($stmt,'bind_param'),$ids);
$stmt->execute();
$stmt->bind_result($tag_id, $tag_name, $tag_desc, $tag_popularity);
while ($stmt->fetch()) {
printf ("%s\n", $tag_name);
}
If the implode array_fill
is confusing, it just is a shorthand way of creating an array of the same size as $ids
full of "?"
, then turning them to a csv.
UPDATE: Non bind params way
Of course, if you want to skip the bind params nonsense, and you can trust the list of $ids
to already be sanitized, you can just do this instead, and skip the bind_params section:
$rawQuery = 'SELECT * FROM core_tags WHERE tag_id IN (';
$rawQuery .= implode(',',$ids);
$rawQuery .= ') GROUP BY tag_id ORDER BY tag_popularity ASC';
If you can't trust the data:
function clean_ids(&$item){
$item = intval($item);
}
$clean_ids = array_walk($ids,'clean_ids');
$rawQuery = 'SELECT * FROM core_tags WHERE tag_id IN (';
$rawQuery .= implode(',',$clean_ids);
$rawQuery .= ') GROUP BY tag_id ORDER BY tag_popularity ASC';
I'm not sure about PHP, but usually when you create a parameterized query like the one you're creating using only one parameter for the list of options in the 'IN' you would en up with something like:
select * from core_tags WHERE tag_id IN ('1,2,3')
that will not do what you want... you would need to add a parameter to the query for each value in the IN that you want
精彩评论