Una dichiarazione preparata, `DOVE .. IN(..)` query e l’ordinamento con MySQL

Immaginare abbiamo una query:

SELECT * FROM somewhere WHERE `id` IN(1,5,18,25) ORDER BY `name`;

e un array di Id per scaricare: $ids = array(1,5,18,25)

Con le istruzioni preparate è consigliato per preparare una dichiarazione e chiamata più volte:

$stmt = $mysqli->prepare('SELECT * FROM somewhere WHERE `id`=?;');
foreach ($ids as $id){
    $stmt->bind_params('i', $id);
    $stmt->exec();
    }

Ma ora dovrò ordinare i risultati manualmente. Ho qualche alternativa?

  • Secondo il link che hai fornito penso che il ragionamento per la preparazione di dichiarazioni è stata la necessità di AGGIORNAMENTO, che non supporta più gli aggiornamenti in una query. Mentre la Selezione e quindi la query è sufficiente.
  • Ero convinto che le istruzioni preparate non sono buone in questi casi. L’unica bella soluzione e ‘andare in una query’ e fanno di questo array di Id ordinato lì, non qui.
InformationsquelleAutor kolypto | 2010-09-13

 

7 Replies
  1. 23

    si potrebbe fare in questo modo:

    $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

    Utilizzo di questo che si sta chiamando bind_param per ogni id e hai ordinamento fatto da mysql.

    • Sì, ma la cosa brutta è che la query non può essere riutilizzato in modo non c’è bisogno di preparare a tutti 🙂
    • Tync: minore è Il numero di viaggi di database, in meglio. Siete i benvenuti a bastone per il PreparedStatement vincoli, ma non scala, se è necessario eseguire 10/20/50/100/1000+ query alla tabella stessa.
    • Non sarebbe meglio creare una vista per questa affermazione, dal momento che non poteva essere riutilizzato in entrambi i modi?
    • Pony, un buon punto sulla scala! Sembra preparato dichiarazioni non in grado di gestire tutto in modo efficiente. Grazie!
    • Tync: Sì, Preparati non sono Affermazioni di un proiettile d’argento
    • Schumacher: mi manca qualcosa? Non vedo quali benefici da un punto di vista sarebbe per il passaggio di parametri di filtraggio. E ‘ solo una stored istruzione SQL…
    • Pony: Viste vengono solo memorizzate le istruzioni SQL. Stavo confrontando l’uso di una dichiarazione preparata l’utilizzo di questo tipo di query, ma ho letto male il codice. :S mi Dispiace per la confusione.
    • Questo è problematico in php 5.3 per questo motivo: ca.php.net/manual/en/mysqli-stmt.bind-param.php#96770
    • strano come nessuno di non notare un filtro in ingresso. Uno dei vantaggi dei prodotti DOP e questo metodo consente di essere utilizzato.
    • Istruzioni preparate non solo per il riutilizzo! Essi forniscono inoltre l’associazione di variabile, il che significa che la traduzione dal PHP tipi di dati e tipi di dati SQL viene gestita dal connettore (o anche di database, il che significa che meno di pensare e di maggiore sicurezza. Puro bonus!

  2. 6

    Credo che questo sia il più semplice possibile risposta :

    $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();

    Così a lungo array di Id non contiene chiavi o tasti con caratteri illegali, wil lavoro.

  3. 5

    Avuto lo stesso problema e in aggiunta alla risposta di @slitta di 7 anni fa, qui è una possibilità, senza fare la call_user_func_array(array($stmt, 'bind_param'), $ids); passo, ma solo chiamare bind_params una volta:

    $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();
    • Geniale! Grazie per questo e per avermi mostrato la ... operatore lavora in PHP.
  4. 3

    Io aggiungo la definitiva slow & brutto soluzione che, tuttavia, utilizza istruzioni preparati per QUALSIASI numero di elementi di matrice 🙂 3 dichiarazioni sono universali per ogni caso e può essere riutilizzato ovunque.

    1. CREATE TEMPORARY TABLEid(idINT );
    2. INSERT INTOidVALUES(?); questo permetterà di inserire il vostro Id
    3. SELECTidFROMidLEFT JOIN .... ; utilizzare i dati da altre tabelle per ordinare il ids elenco
    4. SELECTidFROMid; selezionare tutto torna

    Altrimenti dovrete utilizzare IN (?,?,?,.... o ordinare le righe manualmente. L’idea migliore è utilizzare semplici MySQL-query, o, cercare di ottenere l’elenco di Id già ordinati nel modo che ti piace.

  5. 0

    Avete considerato la riscrittura è originale query con JOIN e la clausola WHERE per ottenere l’ID è necessario per evitare la necessità di una clausola WHERE IN? Sono venuto qui con la stessa domanda, e dopo aver esaminato le possibili soluzioni, ho realizzato un INNER JOIN è stata la mia soluzione.

    • Che era la logica interna: l’app necessaria per recuperare N utenti con id, fornita dall’esterno. Felice che il tuo caso non è così 🙂

Lascia un commento