Esta declaración es legal (en otras palabras, no FROM
se requiere):
SELECT x = 1;
SELECT x = 1 WHERE 1 = 1; -- also try WHERE 1 = 0;
El truco es cuando introduce un nombre de columna que claramente no puede existir. Entonces estos fallan:
SELECT name WHERE 1 = 1;
SELECT x = 1 WHERE id > 0;
Mensaje 207, Nivel 16, Estado 1
Nombre de columna no válido 'nombre'.
Mensaje 207, Nivel 16, Estado 1
Nombre de columna no válido 'id'.
Pero cuando la columna no válida se introduce en algo así como una subconsulta, lo que hace SQL Server cuando no puede encontrar esa columna en el alcance interno de la subconsulta, es transversal a un alcance externo y hace que la subconsulta esté correlacionada con ese alcance externo. Esto devolverá todas las filas, por ejemplo:
SELECT * FROM sys.columns WHERE name IN (SELECT name WHERE 1 = 1);
Porque esencialmente dice:
SELECT * FROM sys.columns WHERE name IN (SELECT sys.columns.name WHERE 1 = 1); /*
^^^^^^^^^^^ -----------
| |
----------------------------------- */
Ni siquiera necesita una WHERE
cláusula en la subconsulta:
SELECT * FROM sys.columns WHERE name IN (SELECT name);
Puede ver que realmente está mirando la tabla de alcance exterior, porque esto:
SELECT * FROM sys.columns WHERE name IN (SELECT name WHERE name > N'x');
Devuelve muchas menos filas (11 en mi sistema).
Esto implica el cumplimiento del estándar sobre el alcance. Puede ver cosas similares cuando tiene dos tablas #temp:
CREATE TABLE #foo(foo int);
CREATE TABLE #bar(bar int);
SELECT foo FROM #foo WHERE foo IN (SELECT foo FROM #bar);
Obviamente, esto debería error, lo correcto, ya que no es foo
en #bar
? No Lo que sucede es que SQL Server dice: "Oh, no encontré un foo
aquí, debes haber querido decir el otro".
Además, en general, lo evitaría NOT IN
. NOT EXISTS
tiene el potencial de ser más eficiente en algunos escenarios, pero lo más importante es que su comportamiento no cambia cuando es posible que la columna objetivo lo sea NULL
. Vea esta publicación para más información .
Reproduje esto en 2016 con un ejemplo simplificado:
Parece que c2 y c3 se evalúan para cada fila.
fuente
En SQL Server, la sintaxis SELECT no requiere la sección FROM. Si omite FROM, la instrucción select usará la tabla "ficticia" que tiene una fila y ninguna columna. Entonces
devolverá una fila si la expresión es verdadera y no habrá filas cuando sea falsa.
fuente
select c
yc
no existe en algún objeto externo. Estoy de acuerdo en queFROM
no es necesaria, pero la mecánica de juego aquí cuando nombre explícitamente una columna que hace existir en un ámbito exterior son definitivamente diferente a una tabla ficticia, y si usted no proporciona una constante para una columna que no lo hace existe, obtiene un error de tiempo de ejecución, por lo que tampoco hay una tabla ficticia allí. La tabla ficticia puede entrar en juego en otros escenarios, pero no cuando la referencia está en una tabla de subconsulta / derivada.SELECT 'x' AS c
es un escenario completamente diferente al de los OP, que acaba de decirSELECT c
. En una subconsulta / tabla derivada.