Estou tentando entender esse comportamento estranho.
- Este lote seleciona 1 e, em seguida, falha porque a tabela não existe. Isso faz sentido.
SELECT 1;
SELECT 1
FROM NonexistentTable;
- Se eu estivesse tentando escrever um script infalível, talvez pudesse verificar a existência da tabela primeiro. Isso seleciona 1 e termina sem gerar nenhum erro. Até agora tudo bem.
SELECT 1;
IF EXISTS (
SELECT 1
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'NonExistentTable'
)
BEGIN
SELECT 1
FROM NonExistentTable;
END
- Este lote seleciona 1 e, em seguida, falha, porque o procedimento não existe. Que é razoável.
SELECT 1;
EXECUTE sp_nonexisting_procedure;
- Este lote se recusa a executar imediatamente, o que é inconsistente com o cenário observado anteriormente. Por que?
SELECT 1;
SELECT NonexistentColumn
FROM sys.databases;
- É ainda mais preocupante em scripts, onde tento verificar explicitamente a existência da coluna. Vamos criar a tabela para o experimento:
CREATE TABLE ExistingTable(Id INT, [Name] NVARCHAR(255));
GO
E então execute este ↓↓↓↓. Isso falha completamente, mesmo sem selecionar 1 também.
SELECT 1;
IF EXISTS (
SELECT 1
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'ExistingTable'
AND COLUMN_NAME = 'NonexistingColumn'
)
BEGIN
SELECT NonexistingColumn
FROM ExistingTable;
END
GO
Por que a existência de colunas é verificada logo após o envio da consulta, sem nem mesmo tentar executar partes válidas da consulta primeiro?
O que torna ainda mais intrigante para mim é que as tabelas são verificadas apenas quando a execução as atinge. (E ingenuamente, eu esperaria que as tabelas fossem mais importantes, portanto, obtendo verificações mais rigorosas/anteriores.)
Para referência, o que você está perguntando é a diferença entre um erro de tempo de execução e um erro de tempo de compilação/análise. As verificações de existência de coluna estão acontecendo no tempo de compilação/análise aqui.
Meu palpite de que tabelas inexistentes não são verificadas até o tempo de execução é porque é válido em T-SQL especificar e referenciar uma tabela temporária que ainda não existe, em determinados contextos, por exemplo, dentro de um procedimento. Isso ocorre porque as tabelas temporárias têm escopo para a sessão que as cria e, portanto, podem não existir em tempo de compilação, mas podem ser criadas em tempo de execução por outra fonte, por exemplo, outro procedimento pai que chama o procedimento filho que faz referência à referida tabela temporária.