views:

47

answers:

4

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  A: 

No, it's not recommended, if you are to fetch certain records from the database using ORDER BY clause.

Tomasz Kowalczyk
+3  A: 

Hi,

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.

sled
Yep, but the bad thing is that the query can't be reused so there's no need to prepare it at all :)
o_O Tync
@o_O Tync: The fewer database trips, the better. You're welcome to stick to the PreparedStatement constraints, but it won't scale if you need to run 10/20/50/100/1000+ queries to the same table.
OMG Ponies
Wouldn't it be better to just create a view for this statement since it couldn't be reused either way?
Ryan Schumacher
@OMG Ponies, a good point about scaling! Looks like prepared statements can't handle *everything* in an efficient way. Thanks!
o_O Tync
@o_O Tync: Yeah, Prepared Statements are not a silver bullet
OMG Ponies
@Ryan Schumacher: Am I missing something? I don't see what benefit a view would be for passing filtration parameters. It's just a stored SQL statement...
OMG Ponies
@OMG Ponies: Views are just stored SQL statements. I was comparing the use of a prepared statement using static query, but I misread the code. :S Sorry for the confusion.
Ryan Schumacher
+1  A: 

An alternative would be to use PHP usort function on the result object, but this is "manual."

See this: http://stackoverflow.com/questions/124266/sort-object-in-php

Ryan Schumacher
A: 

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.

  1. CREATE TEMPORARY TABLEids(idINT );
  2. INSERT INTOidsVALUES(?); this will insert your IDs
  3. SELECTidFROMidsLEFT JOIN .... ; use data from other tables to sort the ids list
  4. SELECTidFROMids; 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.

o_O Tync