2011-02-22 26 views
6

Tengo una consulta que usa la cláusula IN. He aquí una versión simplificada:La columna no existe en la cláusula IN, pero SQL ejecuta

SELECT * 
    FROM table A 
    JOIN table B 
    ON A.ID = B.ID 
WHERE B.AnotherColumn IN (SELECT Column FROM tableC WHERE ID = 1) 

tableC no tiene una columna Column, pero la consulta se ejecuta muy bien con ningún mensaje de error. ¿Alguien puede explicar por qué?

+0

Esto debería darle un error * Sintaxis incorrecta cerca de la palabra clave 'FROM'. * –

+1

@astander: Estoy de acuerdo, debería dar un error, pero no lo hace –

+0

Lo siento, quise decir si el nombre de la columna real era ' Columna'. –

Respuesta

13

Esto funcionará si una tabla en la consulta externa tiene una columna de ese nombre. Esto se debe a que los nombres de las columnas de la consulta externa están disponibles para la subconsulta, y podría querer indicar deliberadamente que seleccione una columna de consulta externa en la lista SELECCIONAR de su subconsulta.

Por ejemplo:

CREATE TABLE #test_main (colA integer) 
CREATE TABLE #test_sub (colB integer) 

-- Works, because colA is available to the sub-query from the outer query. However, 
-- it's probably not what you intended to do: 
SELECT * FROM #test_main WHERE colA IN (SELECT colA FROM #test_sub) 

-- Doesn't work, because colC is nowhere in either query 
SELECT * FROM #test_main WHERE colA IN (SELECT colC FROM #test_sub) 

Como observa Damien, la forma más segura de protegerse de este no muy obvia "Gotcha" es entrar en el hábito de clasificar los nombres de columna en la subconsulta:

-- Doesn't work, because colA is not in table #test_sub, so at least you get 
-- notified that what you were trying to do doesn't make sense. 
SELECT * FROM #test_main WHERE colA IN (SELECT #test_sub.colA FROM #test_sub) 
+1

Tienes que amar Subconsultas correlacionadas. Útil en muchas áreas y causa dolor a quienes no lo conocen: http://en.wikipedia.org/wiki/Correlated_subquery –

+1

@Stephen Heck, hace más de una década que conozco este tema y todavía se dispara. a mí de vez en cuando. Creo que probablemente fui el primero en responder porque lo hice una vez más la semana pasada ... Al menos, con una larga experiencia, normalmente es un rápido "¡Oh!" seguido de una solución, en lugar de dos horas de desconcertar por qué no estoy obteniendo ningún resultado. –

+0

@Matt Gibson: Una cosa que no se ha aclarado, ¿qué es exactamente lo que recupera la consulta 'OUTER'? –

3

Si desea evitar esta situación en el futuro (que Matt Gibson ha explicado), vale la pena adoptar el hábito de usar siempre alias para especificar columnas. Por ejemplo:

SELECT * 
    FROM table A 
    JOIN table B 
    ON A.ID = B.ID 
WHERE B.AnotherColumn IN (SELECT C.Column FROM tableC C WHERE C.ID = 1) 

Esto le habría dado un mensaje de error (obsérvese también que se especifica el alias en la cláusula donde - si no había una columna de ID en TableC, tendría también tenía problemas adicionales)

+0

+1 Sí, ese es un buen punto, y lo he agregado a mi respuesta. –