Esiste un modo semplice in PL / pgSQL per verificare se una query non ha restituito alcun risultato?


16

Attualmente sto sperimentando un po 'con PL / pgSQL e voglio sapere se esiste un modo più elegante per fare qualcosa del genere:

select c.data into data from doc c where c.doc_id = id and c.group_cur > group_cur order by c.id desc limit 1;
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        select c.data into data from doc c where c.doc_id = id and c.global_cur > global_cur order by c.id desc limit 1;
        EXCEPTION
            WHEN NO_DATA_FOUND THEN
                RETURN NULL;

Risposte:


21

I blocchi di eccezioni sono pensati per intercettare errori, non per controllare le condizioni. In altre parole, se una condizione può essere gestita in fase di compilazione, non deve essere intrappolata come errore ma risolta dalla normale logica del programma.

Nella sezione Errori di trapping della documentazione PL / PgSQL è possibile trovare questo suggerimento:

Suggerimento: un blocco contenente una clausola EXCEPTION è significativamente più costoso per entrare e uscire di un blocco senza uno. Pertanto, non utilizzare EXCEPTION senza necessità.

Invece usando le eccezioni (non valido) o IF / THEN / ELSIF (meglio), puoi riscriverlo in una query:

SELECT c.data into data
FROM  doc c
WHERE c.doc_id = id
  and (
    c.group_cur > group_cur
    or
    c.global_cur > global_cur
  )
ORDER BY
  -- this will make group always preferred over global
  case when c.group_cur > group_cur then 1 else 2 end ASC,
  -- and this is your normal ordering
  c.id DESC
limit 1;

Se vuoi davvero due query, puoi usare la variabile FOUND speciale per verificare se la query precedente ha dato qualche risultato:

select c.data into data
from doc c
where c.doc_id = id and c.group_cur > group_cur
order by c.id desc limit 1;
if not found then
    select c.data into data
    from doc c
    where c.doc_id = id and c.global_cur > global_cur
    order by c.id desc limit 1;
    if not found then return null; end if;
end if;

Segue obbligatoriamente i link RTFM :-)

Vedi questo per la descrizione della FOUNDvariabile, e questo per IF/ THENblocchi.


13

Puoi esaminare una variabile speciale TROVATA di tipo booleano. Dalla documentazione:

FOUND inizia falso all'interno di ogni chiamata di funzione PL / pgSQL. È impostato da ciascuno dei seguenti tipi di dichiarazioni:

Un'istruzione SELECT INTO imposta FOUND true se viene assegnata una riga, false se non viene restituita alcuna riga.

Un'istruzione PERFORM imposta FOUND true se produce (e scarta) una o più righe, false se non viene prodotta alcuna riga.

Le istruzioni UPDATE, INSERT e DELETE impostano FOUND true se almeno una riga è interessata, false se nessuna riga è interessata.

Un'istruzione FETCH imposta FOUND true se restituisce una riga, false se non viene restituita alcuna riga.

Un'istruzione MOVE imposta FOUND true se riposiziona correttamente il cursore, false in caso contrario.

Un'istruzione FOR o FOREACH imposta FOUND true se scorre una o più volte, altrimenti false. TROVATO è impostato in questo modo all'uscita dal loop; all'interno dell'esecuzione del loop, FOUND non viene modificato dall'istruzione loop, sebbene possa essere modificata dall'esecuzione di altre istruzioni all'interno del corpo del loop.

Le istruzioni RETURN QUERY e RETURN QUERY EXECUTE impostano FOUND true se la query restituisce almeno una riga, false se non viene restituita alcuna riga.

Altre istruzioni PL / pgSQL non cambiano lo stato di FOUND. Si noti in particolare che EXECUTE modifica l'output di GET DIAGNOSTICS, ma non cambia FOUND.

TROVATO è una variabile locale all'interno di ciascuna funzione PL / pgSQL; qualsiasi modifica ad esso influisce solo sulla funzione corrente.


ma un select intoche non restituisce dati genererà comunque un'eccezione, giusto?
Jack dice di provare topanswers.xyz l'

3
generalmente no, genera eccezioni solo se viene specificata la clausola
STRICT

ah sì, il mio male - anche se questo non significa che il gestore delle eccezioni nell'esempio OP non funzionerà mai? :-)
Jack dice di provare topanswers.xyz l'

1
@JackDouglas: nessun dato non è generalmente causa di un'eccezione (ad eccezione di casi speciali come il modificatore STRICT sopra). L'OP aveva un'idea sbagliata lì.
Erwin Brandstetter,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.