2012-05-08 5 views
5

ho bisogno di fare una semplice queryCome utilizzare istruzioni preparate nelle query con una clausola IN in PHP

$array_of_ids = array(); 
//poulate $array_of_ids, they don't come from another db but from Facebook 
//so i can't use a subquery for the IN clause 
$wpdb->prepare("SELECT id from table where id IN (%d, %d)", $array_of_ids [0], $array_of_ids [1]); 

La domanda è, se ho 200 elementi dell'array, qual è il modo corretto di gestire questo? Devo creare manualmente la query con 200 %d? Ho bisogno di questa query perché devo "sincronizzare" il mio database con i dati di Facebook e devo controllare se l'utente che ho nel db è presente, aggiornare quelli che sono presenti, inserire nuovi utenti ed eliminare quelli che non sono miei amici.

+0

Vedi se [questa domanda] [1] non risponde alla tua domanda [1]: http://stackoverflow.com/questions/327274/mysql-prepared-statements-with-a-variable-size-variable-list –

risposta

3

Se si sa per certo che gli elementi dell'array sono numerici:

$wpdb->prepare("SELECT id FROM table WHERE id IN (" 
    . implode(',',$array_of_ids) . ")"); 

In caso contrario, è possibile utilizzare il vsprintf forma di prepare passare nella matrice di parametri:

$wpdb->prepare("SELECT id FROM table WHERE id IN (" 
    . str_repeat("%d,", count($array_of_ids)-1) . "%d)" , $array_of_ids); 
+3

Un po 'di sconfiggere l'intero scopo dello stato preparato lì, aren'tcha. – cHao

+0

Si può fare un 'implode (',', array_map ('intval', $ array_of_ids))' per assicurarsi che siano, di fatto, numerici. –

+0

Punti giusti; mostrando anche un approccio alternativo nella mia risposta rivista. – eggyal

0

Sì, sql dinamico è il modo qui. Fortunatamente, gli interi sono facili da non rovinare.

$vals = array_filter(array_map('intval', $vals)); 

assicurarsi di avere almeno un valore e quindi imploderlo. Non c'è bisogno di una dichiarazione preparata qui, basta eseguire lo sql.

1

non sono sicuro che questo è un approccio buona, ma si poteva fare in questo modo:

$sql = "SELECT id from table where id IN (" 
    . implode(',', array_fill(0, count($array_of_ids), "%d")) 
    . ")"; 

call_user_func_array(array($wpdb, 'prepare'), $array_of_ids); 

Questo costruisce una stringa con il numero appropriato di %d, quindi utilizza call_user_func_array fare in modo dinamico.

Detto questo, non sono sicuro che questo è davvero un caso in cui le dichiarazioni preparate valgono la seccatura, data la facilità con cui disinfettare gli interi.

+0

array_map() faccia bene il trucco, ma se uso la mappa di array in questo modo potrei facilmente saltare l'istruzione preparata :) –

-1

Si può fare questo:

$query = $wpdb->prepare("SELECT id from table where id IN :param"); 
$query->bindParam("param", "(".implode(',', array_map('intval', $array_of_ids)).")"); 
+1

Sicuramente ' array_map ('intval', ...) 'garantisce sicurezza dall'iniezione SQL? – eggyal

+0

sì hai ragione;) –

+0

Mi sembra che se si associa 'param', sarà escape SQL, quotato e trattato come una stringa ... non come un elenco di cose. A meno che MySQL non riesca a interpretare le stringhe come elenchi, questo probabilmente non funzionerà. – cHao

0

Dal momento che questa non ha una risposta accettato ancora Andrò con il mio approccio con array_filter

$array_of_ids = array(0,1,1,2,3,5,8,13); 

echo "SELECT id from table where id IN (".implode(',', array_filter($array_of_ids,'is_int')).")"; 

uscita volontà

SELECT id from table where id IN (0,1,1,2,3,5,8,13) 

mentre

$array_of_ids = array('zero',1,true,2,3,5,8,'thirteen'); 

echo "SELECT id from table where id IN (".implode(',', array_filter($array_of_ids,'is_int')).")"; 

uscita volontà

SELECT id from table where id IN (1,2,3,5,8) 

prega di notare che is_int non funziona con $ _GET variabili in modo da utilizzare al posto is_numeric