2012-07-31 11 views
16

Sto cercando di imparare SQL, utilizzando PostgreSQL 9.1.3. Mi piacerebbe capire un comportamento che mi sembra inconsistente. Vale a dire:PostgreSQL nested CTE e UNION

Questo funziona:

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

ottengo questo:

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

Questo funziona:

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

Risultato:

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

Questo funziona anche:

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

ottengo questo:

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

Ma questo non non lavoro:

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

Risultato:

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

Per il mio modo di pensare, o l'ultimo dovrebbe avere successo o uno degli altri dovrebbe fallire. Non vedo lo schema. C'è qualche regola generale che mi consenta di prevedere quali combinazioni di CTE e UNION annidate funzioneranno o meno?

+0

Anche se la query finale sembra scomoda, dovrebbe essere ok, IMHO. Potrebbe essere un errore di precedenza/associatività nel parser. Esistono alcune restrizioni semantiche (nessuna CTE ricorsiva annidata, IIRC); forse il parser è troppo schizzinoso, o troppo felice. Personalmente, uso un sacco di CTE annidate (fino a 4 livelli di profondità), ma uso raramente UNION, tranne che nelle CTE ricorsive. – wildplasser

+2

@AdamMackler dovresti metterlo come risposta alla tua stessa domanda – araqnid

+3

Tom Lane riconoscendo che hai trovato un bug, è qualcosa come un'approvazione ufficiale che hai posto una buona domanda. Per favore pubblica ciò che hai ricevuto dalla lista come risposta e assicurati di aggiungere un collegamento alla discussione. –

risposta

17

Il mistero è risolto: il comportamento che stavo osservando è un bug noto. Ho inviato lo stesso post originale a un elenco specifico per PostgreSQL e ottenuto questa risposta:.

Questo è un bug :-(Il codice di analisi di analisi sembra pensare che con può essere collegato solo al livello superiore o un SELECT a livello di foglia all'interno di un albero delle operazioni set , ma la grammatica segue lo standard SQL che non dice nulla di simile. Il WITH viene accettato e collegato all'UNION a livello intermedio che è dove sintatticamente dovrebbe andare, e quindi viene completamente ignorato durante l'analisi dell'analisi.Verrà visualizzato su che lo fissa.

 regards, tom lane 

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

+3

Sembra che questo sia stato corretto in 9.2 beta3. Cito la newsletter: '* Risolto problema con le operazioni di set (UNION/INTERSECT/EXCEPT)'. –

+2

Ho appena installato 9.2beta3 e sì, il comando non funzionante nel mio post originale ora funziona come previsto. Grazie per il testa a testa. –

+0

Fantastico! Grazie per aver rintracciato questo! La tua domanda merita più voti. :) A proposito, è incoraggiato ad accettare la propria risposta (corretta) in tal caso. –