Esta declaração é legal (em outras palavras, não FROM
é necessária):
SELECT x = 1;
SELECT x = 1 WHERE 1 = 1; -- also try WHERE 1 = 0;
O truque é quando você introduz um nome de coluna que claramente não pode existir. Portanto, estes falham:
SELECT name WHERE 1 = 1;
SELECT x = 1 WHERE id > 0;
Mensagem 207, Nível 16, Estado 1
Nome da coluna inválido 'name'.
Mensagem 207, Nível 16, Estado 1
Nome da coluna inválido 'id'.
Mas quando a coluna inválida é introduzida em algo como uma subconsulta, o que o SQL Server faz quando não consegue encontrar essa coluna no escopo interno da subconsulta, é direcionado para um escopo externo e torna a subconsulta correlacionada a esse escopo externo. Isso retornará todas as linhas, por exemplo:
SELECT * FROM sys.columns WHERE name IN (SELECT name WHERE 1 = 1);
Porque é essencialmente dizendo:
SELECT * FROM sys.columns WHERE name IN (SELECT sys.columns.name WHERE 1 = 1); /*
^^^^^^^^^^^ -----------
| |
----------------------------------- */
Você nem precisa de uma WHERE
cláusula na subconsulta:
SELECT * FROM sys.columns WHERE name IN (SELECT name);
Você pode ver que realmente está olhando para a tabela com escopo externo, porque isso:
SELECT * FROM sys.columns WHERE name IN (SELECT name WHERE name > N'x');
Retorna muito menos linhas (11 no meu sistema).
Isso envolve a adesão ao padrão sobre o escopo. Você pode ver coisas semelhantes quando tiver duas tabelas #temp:
CREATE TABLE #foo(foo int);
CREATE TABLE #bar(bar int);
SELECT foo FROM #foo WHERE foo IN (SELECT foo FROM #bar);
Obviamente, isso deve erro, direito, uma vez que não é foo
em #bar
? Não. O que acontece é que o SQL Server diz: "Ah, eu não encontrei um foo
aqui, você deve ter pensado no outro".
Além disso, em geral, eu evitaria NOT IN
. NOT EXISTS
tem o potencial de ser mais eficiente em alguns cenários, mas o mais importante é que seu comportamento não muda quando é possível que a coluna de destino possa ser NULL
. Veja este post para mais informações .
Reproduzi isso em 2016 com um exemplo simplificado:
Parece que c2 e c3 são avaliados para cada linha.
fonte
No SQL Server, a sintaxe SELECT não requer a seção FROM. Se você omitir FROM, a instrução select usará a tabela "fictícia" que possui uma linha e nenhuma coluna. assim
retornará uma linha se a expressão for verdadeira e nenhuma linha quando for falsa.
fonte
select c
ec
não existe em algum objeto externo. Concordo queFROM
não é necessária, mas a mecânica de jogo aqui quando você nomear explicitamente uma coluna que faz existir em um escopo externo são definitivamente diferente do que uma tabela fictícia, e se você não fornecer uma constante para uma coluna que não faz existe, você recebe um erro de tempo de execução, portanto, não há nenhuma tabela fictícia lá. A tabela fictícia pode entrar em jogo em outros cenários, mas não quando a referência está em uma subconsulta / tabela derivada.SELECT 'x' AS c
é um cenário completamente diferente dos OP, que acabamos de dizerSELECT c
. Em uma subconsulta / tabela derivada.