Du har själv fetstilt nyckelsatsen i manualen:
Hela texten i en SQL-funktion tolkas innan någon av den exekveras.
Läs även om The Parser Stage i manualen.
Den består av två huvuddelar:parser och förvandlingsprocessen . Citerar manualen:
förvandlingsprocessen tar trädet som lämnats tillbaka av parserns asinput och gör den semantiska tolkningen som behövs för att förstå vilka tabeller, funktioner och operatorer som hänvisas till av frågan.
Om en SQL-funktion innehåller dessa kommandon:
CREATE TABLE foo (...);
INSERT INTO foo VALUES(...);
Båda uttalandena planeras praktiskt taget samtidigt (baserat på samma ögonblicksbild av systemkatalogerna). Därför INSERT
kan inte se tabellen "foo" som förmodligen skapades med föregående CREATE
kommando. Det skapar ett av följande problem :
-
Om det inte finns någon annan tabell med namnet "foo" i din
search_patch
(ännu), Postgres klagar när de försöker skapa funktionen:ERROR: relation "foo" does not exist
-
Om en annan tabell med namnet "foo" redan finns i din
search_patch
(och du använder inte motstridiga kolumnnamn), Postgres planerarINSERT
baserat på den redan existerande tabellen. Vanligtvis resulterar det i ett fel vid körningstid , om några värden orsakar konflikter i (fel!) tabellen. Eller, med lite otur, kan den till och med skriva till den tabellen utan felmeddelande! Mycket lömsk bugg.
Det kan inte hända med en PL/pgSQL funktion, eftersom den behandlar SQL-kommandon som förberedda satser, planerade och utförda sekventiellt . Så varje sats kan se objekt skapade i tidigare satser.
Följaktligen är satser som aldrig besöks aldrig ens planerade - till skillnad från med SQL-funktioner. Och exekveringsplanen för satser kan cachelagras inom samma session - också till skillnad från SQL-funktioner. Läs detaljer om plancachning i PL/pgSQL-funktioner i manualen här.
Varje tillvägagångssätt har fördelar för vissa användningsfall. Mer läsning:
- Skillnaden mellan språk sql och språk plpgsql i PostgreSQL-funktioner