2009-05-15 13 views
6

Algo que he notado recientemente es que las personas usan IN cuando parece algo inapropiado. Siento que me estoy perdiendo un truco, ¿tal vez hay ganancias de velocidad o algo así?DONDE x EN (5) vs DONDE x = 5 ... ¿por qué usar IN?

Esta consulta:

SELECT * FROM pages WHERE is_visible IN ($visibility) 

¿Por qué usar eso? ¿Por qué no:

SELECT * FROM pages WHERE is_visible = $visibility 

Claro, si se tratara de esto:

SELECT * FROM pages WHERE is_visible 
IN ($visibility,$invisibility,$somethingelse) 

Entonces WHERE x IN (1,2,3) es una mejor alternativa a WHERE x = 1 OR x = 2 OR x = 3, ¿verdad? Pero seguramente este es el escenario único donde debería usar IN?

De todos modos gracias por su tiempo - ¡Espero sus respuestas!

+1

Gracias por las respuestas a todos. En este caso, $ visiblity es confiable y siempre 0 o 1.¡Así que me parece que este uso de "DONDE ... EN ..." es innecesario después de todo! – ledneb

+1

Ahora no siempre significa que siempre lo hará. El desarrollador podría estar preparándose para ese momento "por las dudas". –

+0

YAGNI. El caso de por si acaso nunca viene. –

Respuesta

2

No hay truco aquí para aumentar el rendimiento, pero no creo que haya ninguna actuación golpear a cualquiera. Entonces, ambas formas están bien. Estoy de acuerdo con usted en que el uso de una cláusula IN con un solo parámetro parece divertido, pero aún es bastante fácil de seguir.

Creo que esto probablemente ocurre porque un desarrollador cree que es probable que se permitan múltiples valores en el futuro (de esta manera, la consulta no se cambiaría). O posiblemente el desarrollador esté acostumbrado a escenarios en los que sean posibles múltiples valores, y simplemente lo escribieron de esa manera por costumbre.

+2

Kip Creo que estás equivocado. Obviamente, él no comprende completamente el IN ya que IN no es lo mismo que OR. Si él hizo lo que dijo "Entonces DONDE x EN (1,2,3) es una mejor alternativa que DONDE x = 1 O x = 2 O x = 3, ¿verdad?" – Lee

+1

Gracias Kip. Creo que todas las respuestas a la pregunta son geniales, pero la tuya responde la pregunta en sí :) – ledneb

+0

@Lee: tu comentario perteneció a tu respuesta, no a esta, ya que el comentario no se relaciona con esta respuesta. – Kip

8

Entonces WHERE x IN (1,2,3) es una mejor alternativa a WHERE x = 1 OR x = 2 OR x = 3, ¿verdad? Pero seguramente este es el único escenario donde debería usar IN?

No, puede utilizar IN con una subconsulta también.

... donde el campo de (campo de selección de another_table)

+0

Gracias, Kip. –

+0

Ese es un buen punto. No consideré que IN podría usarse con una subconsulta – ledneb

5

Tal vez se genera dinámicamente $ visibilidad, así:

$visibility = implode(', ', array_map('intval', array(1, 2, 3))); 

Dónde array (1, 2, 3) puede provenir de que no se confía fuentes.

9

¿Se desconoce si $ visibilidad se refiere a un solo valor o valores múltiples? No encaja con su ejemplo, pero he visto tal uso en otros lugares.

+2

Yo, también, he visto esto ... la memoria todavía me atormenta. – rmeador

+0

Mmm, un buen punto; en este caso, sin embargo, la visibilidad siempre es 0 o 1 – ledneb

+0

Si $ visibility se refiere a valores múltiples, ¿cómo se expandirán esos valores en el sql? Si $ visibility = '1,2,3' esto no tiene mucho sentido: SELECCIONE * FROM páginas WHERE is_visible IN ('1,2,3') – ErikE

0

"WHERE x IN (1,2,3)" es lo mismo que "DONDE x = 1 O x = 2 O x = 3" de todos modos.

2

En actos en cualquier tipo de operación de conjunto, mientras que = está en un solo valor. De modo que puede utilizar para múltiples registros en otra tabla, o cualquier otro tipo de estructura de datos que represente valores múltiples.

3

Creo que es más importante entender qué hace IN.

Si lo hace

SELECT * FROM pages WHERE is_visible = $visibility 

En el $ visibilidad anterior tendría que ser una var por lo is_visibile = 1, así que su SQL recoge toda donde is_visible = 1

Dónde

SELECT * FROM pages WHERE is_visible IN ($visibility) 

La $ visibilidad sería una matriz de datos como @Ionut G. Stan ha ilustrado.

Así que su llamada se vería is_visible IN ('1', '2' '3')

Así que ahora su SQL estará recolectando todos los 1,2 & 3 filas.

Espero que tenga sentido. Es una gran diferencia.

+0

No veo cómo responde esto a su pregunta. Él parece muy consciente de lo que significa IN. – Kip

+0

@Lee: a partir de su comentario que ha puesto la respuesta incorrecta: >> Kip, creo que estás equivocado. Obviamente, él no comprende completamente el IN ya que IN no es lo mismo que OR. Si él hizo lo que dijo "Entonces DONDE x EN (1,2,3) es una mejor alternativa a DÓNDE x = 1 O x = 2 O x = 3, ¿verdad?" << El hecho es "X IN (1 , 2,3) "* IS * efectivamente es lo mismo que" X = 1 OR X = 2 O X = 3 ". Si dices que no lo son, ¿en qué circunstancias darían resultados de consulta diferentes? puede haber diferencias en la implementación del motor de la base de datos, pero no hay diferencia desde la perspectiva del recuadro negro. – Kip

1

No, no es un truco. Las dos declaraciones:

SELECT * FROM pages WHERE is_visible IN ($visibility) 
SELECT * FROM pages WHERE is_visible = $visibility 

son casi equivalentes. Observamos que las dos afirmaciones son equivalentes en el caso trivial, por ejemplo, cuando $visibility es un escalar con un valor de 1.

Pero las declaraciones son no equivalente en los casos no triviales cuando $visibility contiene algo más . Podemos observar una diferencia significativa en el comportamiento de las dos formas. Considere lo que sucede con cada forma cuando $visibility es una cadena que contiene estos valores de ejemplo:

 
    '1,2,3' 
    '1 OR 1=1' 
    'select v.val from vals v' 

se observa una diferencia significativa en las sentencias SQL resultantes generadas a partir de las dos formas:

 
    SELECT * FROM pages WHERE is_visible IN (1,2,3) 
    SELECT * FROM pages WHERE is_visible = 1,2,3 
 
    SELECT * FROM pages WHERE is_visible IN (1 OR 1=1) 
    SELECT * FROM pages WHERE is_visible = 1 OR 1=1 

Una gran preocupación aquí, con cualquier forma de la declaración, es el potencial para la inyección SQL. Si $visibility está destinado a ser un valor escalar, usar una variable de vinculación en la declaración es un enfoque más seguro, ya que evita que cualquiera deslice la sintaxis SQL 'adicional' en la instrucción. (Por supuesto, el uso de variables de vinculación no previene todas las inyecciones de SQL, pero es un enfoque adecuado para cerrar un agujero. Usar una variable de vinculación también mejorará la escalabilidad, al menos en algunas plataformas DBMS como Oracle.)

Considerar ¿Qué sucede cuando utilizamos una variable de vinculación (marcador de posición), que sabemos que NO se interpretará como sintaxis SQL. Observamos que las dos declaraciones SON de hecho equivalente:

 
    SELECT * FROM pages WHERE is_visible IN (?) 
    SELECT * FROM pages WHERE is_visible = ? 

para cualquier valor proporcionado para la variable de vinculación.

HTH

+0

Aún tiene la posibilidad de inyección SQL con IN o con iguales, esta respuesta es irrelevante para la pregunta. – Kip

+0

Kip, tienes razón. Eso es lo que estaba tratando de señalar. La pregunta original preguntaba si "faltaban algo". Usted parece haberlo perdido también. Ninguna variante impide la inyección de SQL, que se soluciona más fácilmente con una variable de vinculación. En ese caso, las declaraciones SERÍAN equivalentes, incluso cuando se suministre un valor NULL. Si no se va a molestar en usar una variable de vinculación, las sentencias son _SIGNIFICATIVAMENTE_ diferentes ya que son vulnerables de diferentes maneras, y no se nos proporciona NINGUNA información sobre qué $ visibilidad contiene. Mi respuesta ES relevante. – spencer7593

0

Entonces donde x IN (1,2,3) es una mejor alternativa a donde x = 1 ó x = 2 O x = 3, ¿verdad? Pero seguramente este es el único escenario donde debería usar IN?

IN() y OR son sinónimos sintácticamente equivalentes. Examinar el plan de ejecución para sus dos sugerencias lo mostrará. IN() simplemente es una notación más eficiente y fácil de entender.

Cuestiones relacionadas