Klíčovou větu v manuálu jste si sám označil tučně:
Celé tělo funkce SQL je analyzováno před provedením kterékoli z nich.
Přečtěte si také o The Parser Stage v návodu.
Skládá se ze dvou hlavních částí:analyzátoru a proces transformace . Cituji manuál:
proces transformace vezme strom předaný jako vstup analyzátoru zpět a provede sémantickou interpretaci potřebnou k pochopení, na které tabulky, funkce a operátory se dotaz odkazuje.
Pokud funkce SQL obsahuje tyto příkazy:
CREATE TABLE foo (...);
INSERT INTO foo VALUES(...);
Oba výpisy jsou plánovány prakticky ve stejnou dobu (na základě stejného snímku systémových katalogů). Proto INSERT
nevidí tabulku "foo" pravděpodobně vytvořenou pomocí předchozího CREATE
příkaz. To vytváří jeden z následujících problémů :
-
Pokud neexistuje jiné tabulka s názvem "foo" ve vašem
search_patch
(zatím) si Postgres stěžuje při pokusu o vytvoření funkce:ERROR: relation "foo" does not exist
-
Pokud ve vašem
search_patch
již existuje jiná tabulka s názvem "foo". (a nepoužíváte konfliktní názvy sloupců), Postgres naplánujeINSERT
na základě již existující tabulky. To obvykle vede k chybě v době provádění , pokud nějaké hodnoty způsobí konflikty v (špatné!) tabulce. Nebo, s trochou smůly, může dokonce zapsat do této tabulky bez chybové zprávy! Velmi záludná chyba.
To se nemůže stát s PL/pgSQL funkce, protože zachází s příkazy SQL jako s připravenými příkazy, naplánovanými a provedenými sekvenčně . Každý příkaz tedy může vidět objekty vytvořené v předchozích příkazech.
V důsledku toho příkazy, které nejsou nikdy navštěvovány, nejsou nikdy ani plánovány - na rozdíl od funkcí SQL. A plán provádění příkazů lze uložit do mezipaměti v rámci stejné relace – také na rozdíl od funkcí SQL. Podrobnosti o ukládání do mezipaměti plánu ve funkcích PL/pgSQL si přečtěte v příručce zde.
Každý přístup má pro některé případy použití výhody. Další čtení:
- Rozdíl mezi jazykem sql a jazykem plpgsql ve funkcích PostgreSQL