2012-07-31 13 views
16

Próbuję nauczyć się SQL, używając PostgreSQL 9.1.3. Chciałbym zrozumieć pewne zachowanie, które wydaje mi się niespójne. Słownie:PostgreSQL zagnieżdżone CTE i UNION

to działa:

WITH innermost AS (SELECT 2) 
SELECT * FROM innermost 
UNION SELECT 3; 

uzyskać to:

?column? 
---------- 
     2 
     3 

to działa:

WITH outmost AS (
     (WITH innermost AS (SELECT 2) 
     SELECT * FROM innermost) 
)         
SELECT * FROM outmost; 

Wynik:

?column? 
---------- 
     2 

Działa to również:

WITH outmost AS (
    SELECT 1 
    UNION (WITH innermost AS (SELECT 2) 
     SELECT * FROM innermost) 
) 
SELECT * FROM outmost; 

uzyskać to:

?column? 
---------- 
     1 
     2 

Ale to nie robi pracy:

WITH outmost AS (
    SELECT 1 
    UNION (WITH innermost as (SELECT 2) 
     SELECT * FROM innermost 
     UNION SELECT 3) 
) 
SELECT * FROM outmost; 

Wynik:

ERROR: relation "innermost" does not exist 
LINE 4:   SELECT * FROM innermost 

Moim zdaniem, albo ten ostatni powinien odnieść sukces, albo jeden z pozostałych powinien zawieść. Nie widzę wzoru. Czy istnieje jakaś ogólna zasada, która pozwoliłaby mi przewidzieć, które kombinacje zagnieżdżonych CTE i UNION-ów będą lub nie będą działać?

+0

Choć twój ostateczny zapytanie wygląda niewygodne, powinno być OK, IMHO. Może to być błąd pierwszeństwa/asocjacji w analizatorze składni. Istnieją pewne ograniczenia semantyczne (Brak zagnieżdżonych rekurencyjnych CTE, IIRC); może parser jest zbyt wybredny lub zbyt szczęśliwy dla uruchomienia. Osobiście używam wielu zagnieżdżonych CTE (do 4 poziomów głębokości), ale rzadko używam UNION, z wyjątkiem rekurencyjnych CTE. – wildplasser

+2

@AdamMackler należy umieścić jako odpowiedź na własne pytanie – araqnid

+3

Tom Lane potwierdzając, że znalazłeś błąd, to coś w rodzaju oficjalnej zgody, że zadałeś bardzo dobre pytanie. Opublikuj, co dostałeś z listy jako odpowiedź, i dodaj link do wątku. –

Odpowiedz

17

Tajemnica została rozwiązana: zachowanie, które obserwowałem, jest znanym błędem. Wysłałem ten sam oryginalny post do listy PostgreSQL specyficzne i dostałem taką odpowiedź.

jest to błąd :-(Kod analiza parse wydaje się myśleć, że przy mogą być przyłączone wyłącznie do najwyższego poziomu lub liść poziomu SELECT w drzewie operacji zadanej, ale gramatyka następujący standard SQL, które mówi nic takiego WITH zostanie zaakceptowana, a dołączone do Unii pośredniego szczebla czyli tam, gdzie składniowo należy przejść, i. to zostanie całkowicie zignorowane podczas analizowania składni. Zobaczysz o naprawieniu tego:

 regards, tom lane 

http://archives.postgresql.org/pgsql-novice/2012-07/msg00113.php

+3

Wygląda na to, że zostało to naprawione w wersji 9.2 beta3. Cytuję biuletyn: '* Napraw problem z ustawionymi operacjami (UNION/INTERSECT/EXCEPT)'. –

+2

Właśnie zainstalowałem 9.2beta3 i tak, polecenie nieprzetwarzania w moim oryginalnym wpisie działa teraz zgodnie z oczekiwaniami. Dziękuję za wzloty. –

+0

Fajnie! Dziękujemy za śledzenie tego! Twoje pytanie zasługuje na więcej awansów. :) BTW, zachęca się do zaakceptowania własnej (poprawnej) odpowiedzi w takim przypadku. –