2012-05-08 10 views
5

Necesito hacer una consulta sencillaCómo usar comandos preparados en consultas con una cláusula IN en 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 pregunta es, si tengo 200 elementos de la matriz, lo que es la forma correcta de manejar ¿Tengo que crear manualmente la consulta con 200 %d? Necesito esta consulta porque debo "sincronizar" mi base de datos con los datos de Facebook y tengo que verificar si el usuario que tengo en el archivo db está presente, actualizar los que están presentes, insertar nuevos usuarios y eliminar los que no son mis amigos.

+0

Ver si [esta cuestión] [1] no responde a tu pregunta [1]: http://stackoverflow.com/questions/327274/mysql-prepared-statements-with-a-variable-size-variable-list –

Respuesta

3

Si sabe con certeza que los elementos de la matriz son numéricos:

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

De lo contrario, puede utilizar la forma de preparevsprintf a pasar en el conjunto de parámetros:

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

Un poco derrotar todo el propósito del estado preparado allí, aren'tcha. – cHao

+0

Puedes hacer un 'implode (',', array_map ('intval', $ array_of_ids))' para asegurarte de que sean, de hecho, numéricos. –

+0

puntos equitativos; también muestra un enfoque alternativo en mi respuesta revisada. – eggyal

0

Sí, sql dinámico es el camino aquí. Afortunadamente, es fácil no confundir números enteros.

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

asegúrese de que tiene al menos un valor y luego implosionar ella. No necesita una declaración preparada aquí, simplemente ejecute el sql.

1

no estoy seguro de que este es un enfoque buena, pero podría hacerlo de esta manera:

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

Esto construye una cadena con el número apropiado de %d, a continuación, utiliza call_user_func_array hacer dinámicamente

Dicho esto, no estoy seguro de que este sea realmente un caso en el que las declaraciones preparadas valen la pena, dado lo fácil que es desinfectar enteros.

+0

array_map() hace el truco, creo, pero si uso el mapa de la matriz de esa manera podría omitir fácilmente la instrucción preparada :) –

-1

Usted puede hacer esto:

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

Seguramente array_map ('intval', ...) 'garantiza la seguridad de la inyección SQL? – eggyal

+0

sí, tienes razón;) –

+0

Me parece que si enlazas 'param', se escapará de SQL, se citará y se tratará como una cadena ... no como una lista de cosas. A menos que MySQL haga magia para interpretar cadenas como listas, probablemente esto no funcione. – cHao

0

Dado que este no tiene una respuesta aceptada sin embargo, voy a ir con mi enfoque 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')).")"; 

es la salida

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

mientras

$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')).")"; 

es la salida

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

Tenga en cuenta que is_int no funciona con $ _GET las variables a fin de utilizar is_numeric lugar

Cuestiones relacionadas