2017-01-12 28 views
12

Dlaczego to zapytanie SQL działa, mimo że SELECT brakuje FROM, co oznaczałoby błąd składni. Należy również zauważyć, że zapytanie wyświetla tylko ten, który spełnia klauzulę WHERE.W jaki sposób instrukcja SQL Exists działa nawet, jeśli składnia jest niepoprawna?

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' 
); 

To jest test na SQL Server 2012 i 2014, oto próbka stronie: http://rextester.com/GDGB80815

+9

Pytanie oparte na fałszywych założeniach. Produkt nie zgłasza błędów składniowych, gdy w rzeczywistości nie występują błędy składniowe. –

Odpowiedz

28

SQL Server nie wymaga FROM w oświadczeniu SELECT.

Na przykład, nie ma żadnego błędu w składni zapytanie:

SELECT 2 AS t 
WHERE 0 = 0 

Zwraca jednego wiersza z kolumny t i wartości 2.

Możesz napisać prosty

SELECT 2 AS t 

aby uzyskać ten sam rezultat.


Zapytanie jest taki sam jak ten:

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

Wewnętrzna Customer_Tbl jest aliasem dla kolumny ze stałym 2. Country w WHERE jest kolumną zewnętrznego stołu Customer_Tbl.

Dobrze jest używać AS dla aliasów i całkowicie zakwalifikować kolumny z ich nazwami.


Podczas próby uruchomienia wewnętrznej części osobno

SELECT 2 Customer_Tbl 
WHERE Country = 'MEXICO' 

nie powiodło się, ponieważ nie ma FROM, ale dlatego, że parser nie wie, co jest Country:

Msg 207, Poziom 16, Stan 1, Wiersz 2 Nieprawidłowa nazwa kolumny "Kraj".


Dla kompletności, tutaj jest składnia SELECT oświadczenie w SQL Server od 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> ] 

klauzule opcjonalne są w nawiasach kwadratowych []. Jak widać, wszystkie klauzule są opcjonalne, w tym FROM, z wyjątkiem samego słowa kluczowego SELECT i <select_list>.

5

To ważne. To skorelowanie z powrotem do Customer_Tbl.Country

Jeśli istnieje co najmniej jeden rekord w Customer_Tbl.Country='MEXICO' wówczas gdy istnieje jest TRUE

I'ts ważny tylko wtedy, gdy znajduje się wewnątrz EXISTS chociaż

+0

jeśli spróbujesz skompletować EXIST za pomocą 'FROM Customer_Tbl', to wyświetli inny wynik – jbalintac

+3

@jbalintac To dlatego, że w obecnej wypowiedzi jest interpretacja' Customer_Tbl' jako aliasu kolumny. Jeśli go zmienisz (dodając 'FROM' przed' Customer_Tbl'), to zinterpretujesz 'Customer_Tbl' jako tabelę, a klauzula exist stanie się zupełnie inna. – ZLK

+1

Tak, gdy dodajesz 'FROM Customer_Tbl', nie ma już korelacji z zewnętrznym' Customer_Tbl', 'EXIST' jest zawsze prawdziwe bez względu na to, do którego wiersza odwołuje się zewnętrzny 'Customer_Tbl', więc dostajesz wszystkie wiersze –