开发者

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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜