it-swarm-eu.dev

Existuje v PL / pgSQL jednoduchý způsob, jak zkontrolovat, zda dotaz nevrátil žádný výsledek?

Momentálně trochu experimentuji s PL/pgSQL a chci vědět, jestli existuje elegantnější způsob, jak něco udělat:

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;
17
icefex

Bloky výjimek jsou určeny k zachycení chyb, nikoli ke kontrole podmínek. Jinými slovy, pokud některá podmínka může být zpracována v době kompilace, neměla by být zachycena jako chyba, ale vyřešena běžnou logikou programu.

V sekce Trapping Chyby dokumentace PL/PgSQL najdete takový tip:

Tip: Blok obsahující klauzuli EXCEPTION je výrazně dražší než vstup bez bloku. Proto NEVYUŽÍVEJTE VÝNIMKU bez nutnosti.

Namísto použití výjimek (špatné) nebo IF/THEN/ELSIF (lepší) můžete přepsat na jeden dotaz:

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;

Pokud opravdu chcete dva dotazy, můžete pomocí speciální proměnné FOUND otestovat, zda předchozí dotaz přinesl nějaký výsledek:

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;

Povinné RTFM odkazy folllow :-)

Popis proměnné FOUND viz this a this pro bloky IF/THEN.

21
filiprem

Můžete prozkoumat speciální proměnnou FOUND typu boolean. Z dokumentace:

FOUND začíná falešně v každém volání funkce PL/pgSQL. Je nastaven každým z následujících typů příkazů:

Příkaz SELECT INTO nastaví FOUND na true, pokud je přiřazen řádek, false, pokud není vrácen žádný řádek.

Příkaz PERFORM nastaví FOUND na true, pokud vytvoří (a zahodí) jeden nebo více řádků, false, pokud není vytvořen žádný řádek.

Příkazy UPDATE, INSERT a DELETE nastaví FOUND na true, pokud je ovlivněn alespoň jeden řádek, false, pokud není ovlivněn žádný řádek.

Příkaz FETCH nastaví FOUND na true, pokud vrátí řádek, false, pokud se nevrátí žádný řádek.

Příkaz MOVE nastaví FOUND na true, pokud úspěšně umístí kurzor, v opačném případě false.

Příkaz FOR nebo FOREACH nastaví FOUND na true, pokud se opakuje jednou nebo vícekrát, jinak false. FOUND je nastaven tímto způsobem při opuštění smyčky; uvnitř provádění smyčky FOUND není změněn příkazem smyčky, ačkoli může být změněn provedením jiných příkazů v těle smyčky.

Příkazy RETURN QUERY a RETURN QUERY EXECUTE set FOUND true, pokud dotaz vrátí alespoň jeden řádek, false, pokud není vrácen žádný řádek.

Ostatní příkazy PL/pgSQL nemění stav FOUND. Zejména mějte na paměti, že EXECUTE mění výstup GET DIAGNOSTICS, ale nemění FOUND.

FOUND je lokální proměnná v rámci každé PL/pgSQL funkce; jakékoli jeho změny ovlivní pouze aktuální funkci.

14
alexk