2010-01-21 8 views
9

Cuando ejecuta esta consulta¿Por qué no se ha producido el error "XYZ del nombre de columna no válido" en la sub consulta? aunque el nombre de la columna no está en la tabla de subconsulta?

SELECT CustomerId FROM Stocks.dbo.Suppliers 

Me da este error. Nombre de columna inválido 'CustomerId'. Este error es válido ya que no hay una columna CustomerId en la tabla Proveedores; pero cuando uso la misma consulta en la subconsulta, no da ningún error, por ejemplo, E.g.

SELECT * 
    FROM SomeOtherDb.dbo.Customer 
WHERE CustomerId In(SELECT CustomerId 
         FROM Stocks.dbo.Suppliers) 

Aquí estoy esperando mismo error "nombre de columna no válido", pero consulta se ejecuta sin ningún error.

El nombre completamente calificado es solo una convención, ambos dbs están en el mismo servidor.

CustomerId existe en SomeOtherDb.dbo.Calendario de clientes pero no en subconsulta.

¿Por qué es este comportamiento? ¿Esto es algo con subconservación?

Gracias.

+0

tira el error de la columna no válida en mí en cualquier situación. ¿El nombre completo es solo una convención o un servidor vinculado? – Andrew

+0

El nombre completo es solo una convención. Ambos DB están en el mismo servidor. – Kashif

Respuesta

13

Las subconsultas heredan columnas de las consultas externas.

Supongo que su SomeOtherDb.dbo.Customer tiene una columna CustomerId (que también parece probable de los nombres).

Lo que también probablemente significa que no está haciendo con la subconsulta lo que quiere hacer con ella - si la tabla en la subconsulta no tiene una columna CustomerId (y parece que sí, de lo contrario no habría ningún error cuando ejecutar la subconsulta en sí mismo), luego la subconsulta selecciona y devuelve el CustomerId externo, y como esa es la única columna en la subconsulta, la subconsulta es inútil.

+0

Sí, tiene razón, SomeOtherDb.dbo.Customer tiene la columna CustomerId. – Kashif

+6

Me he encontrado con esto algunas veces, y aunque la respuesta tiene sentido, creo que es un mal diseño en SQL Server (ya sea que implemente o no completamente un estándar ISO SQL). Creo que sería mucho más seguro requerir subconsultas para usar un alias al hacer referencia a columnas en la consulta principal. Mi colega experimentó una tragedia relacionada cuando actualizó por error todas las filas en una tabla de producción debido a un error tipográfico en la subconsulta como la anterior. Hilarity (y restaurar desde copias de seguridad): :) –

+0

Definir explícitamente la tabla (o alias de tabla) para cada columna es una buena práctica: evitará que sus subconsultas obtengan columnas de las tablas incorrectas, y también en uniones regulares (sin subconsultas) evitará conflictos de nombres en caso de que alguien cree nuevas columnas. – drizin

1

La respuesta a su pregunta ("por qué no hay error") es anterior, pero tal vez un poco de ayuda sobre cómo evitar este tipo de problema en el futuro: en lugar de usar una subconsulta para hacer esto, use una combinación izquierda:

SELECT C.* 
FROM SomeOtherDb.dbo.Customer AS C 
LEFT JOIN Stocks.dbo.Suppliers AS S ON C.CustomerId = S.CustomerId 
WHERE S.CustomerID Is Null 

Esta consulta, cuando se construye con una combinación que es posible, por supuesto, siempre se llevará a cabo, así como su original o mejor - y tiene la ventaja añadida de evitar ese problema desagradable anteriormente. Debido a que en esta construcción usará nombres de tabla de forma natural, será más obvio cuando haya un problema, como el mismo nombre de tabla en ambos lados del signo igual. Las subconsultas son una mierda, estoy en una cruzada permanente contra ellos.

(que dijo, sé un montón de personas están en una cruzada contra el aliasing, que he usado anteriormente para simplificar/condensar el código :))

Cuestiones relacionadas