Как оператор SQL Exists работает даже в случае неправильного синтаксиса?

Почему этот SQL-запрос работает, даже если SELECT отсутствует FROM, что будет синтаксической ошибкой. Также обратите внимание, что в запросе отображается только тот, который удовлетворяет предложению WHERE.

CREATE TABLE Customer_Tbl
(
    CustomerName VARCHAR(50), 
    Address VARCHAR(250),
    Country VARCHAR(50)
);


INSERT INTO Customer_Tbl 
VALUES
    ('AAA', '','Philippines'),
    ('BBB', '','Mexico'),
    ('CCC', '','Philippines'),
    ('DDD', '','Mexico'),
    ('EEE', '','Philippines');


SELECT *
FROM Customer_Tbl 
WHERE EXISTS(
    -- This is missing a FROM
    -- running it by itself is a syntax error.
    SELECT 2 Customer_Tbl 
    WHERE Country = 'MEXICO'
);

Это тест на SQL Server 2012 и 2014, здесь онлайн-образец: http://rextester.com/GDGB80815

Ответ 1

SQL Server не требует FROM в инструкции SELECT.

Например, в следующем запросе отсутствует синтаксическая ошибка:

SELECT 2 AS t
WHERE 0 = 0

Он возвращает одну строку со столбцом t и значением 2.

Вы можете написать простой

SELECT 2 AS t

чтобы получить тот же результат.


Ваш запрос такой же:

SELECT *
FROM Customer_Tbl 
WHERE EXISTS(
    SELECT 2 AS Customer_Tbl 
    WHERE Customer_Tbl.Country = 'MEXICO'
);

Внутренний Customer_Tbl является псевдонимом для столбца с константой 2. Country в WHERE - столбец внешней таблицы Customer_Tbl.

Хорошо использовать AS для псевдонимов и полностью квалифицировать столбцы с именами их таблиц.


При попытке запустить внутреннюю часть отдельно

SELECT 2 Customer_Tbl 
WHERE Country = 'MEXICO'

это происходит не из-за отсутствия FROM, а потому, что парсер не знает, что такое Country:

Msg 207, Уровень 16, Состояние 1, Строка 2 Недопустимое имя столбца "Страна".


Для полноты здесь синтаксис оператора SELECT в SQL Server от MSDN:

<SELECT statement> ::=    
    [ WITH { [ XMLNAMESPACES ,] [ <common_table_expression> [,...n] ] } ]  
    <query_expression>   
    [ ORDER BY { order_by_expression | column_position [ ASC | DESC ] }   
  [ ,...n ] ]   
    [ <FOR Clause>]   
    [ OPTION ( <query_hint> [ ,...n ] ) ]   
<query_expression> ::=   
    { <query_specification> | ( <query_expression> ) }   
    [  { UNION [ ALL ] | EXCEPT | INTERSECT }  
        <query_specification> | ( <query_expression> ) [...n ] ]   
<query_specification> ::=   
SELECT [ ALL | DISTINCT ]   
    [TOP ( expression ) [PERCENT] [ WITH TIES ] ]   
    < select_list >   
    [ INTO new_table ]   
    [ FROM { <table_source> } [ ,...n ] ]   
    [ WHERE <search_condition> ]   
    [ <GROUP BY> ]   
    [ HAVING < search_condition > ]   

Дополнительные предложения заключены в квадратные скобки [ ]. Как вы можете видеть, почти все предложения являются необязательными, включая FROM, за исключением самого ключевого слова SELECT и < select_list >.

Ответ 2

Это действительно. Он коррелирует с Customer_Tbl.Country

Если в Customer_Tbl.Country='MEXICO' есть хотя бы одна запись, тогда WHERE EXISTS имеет значение TRUE

Я знаю только, когда он находится внутри EXISTS хотя