Du har selv fremhævet nøglesætningen i manualen:
Hele brødteksten af en SQL-funktion analyseres, før nogen af den udføres.
Læs også om The Parser Stage i manualen.
Den består af to hoveddele:parseren og transformationsprocessen . Citerer manualen:
transformationsprocessen tager træet tilbage af parseren asinput og udfører den semantiske fortolkning, der er nødvendig for at forstå, hvilke tabeller, funktioner og operatorer der refereres til af forespørgslen.
Hvis en SQL-funktion indeholder disse kommandoer:
CREATE TABLE foo (...);
INSERT INTO foo VALUES(...);
Begge udsagn er planlagt på stort set samme tidspunkt (baseret på det samme øjebliksbillede af systemkatalogerne). Derfor INSERT
kan ikke se tabellen "foo", der formentlig er oprettet med den tidligere CREATE
kommando. Det skaber et af følgende problemer :
-
Hvis der ikke er andet tabel med navnet "foo" i din
search_patch
(endnu), Postgres klager når de prøver at oprette funktionen:ERROR: relation "foo" does not exist
-
Hvis en anden tabel ved navn "foo" allerede findes i din
search_patch
(og du bruger ikke modstridende kolonnenavne), vil Postgres planlæggeINSERT
baseret på den allerede eksisterende tabel. Det resulterer typisk i en fejl på udførelsestidspunktet , hvis nogen værdier forårsager konflikter i den (forkerte!) tabel. Eller, med lidt uheld, kan den endda skrive til den tabel uden fejlmeddelelse! Meget lusket fejl.
Det kan ikke ske med en PL/pgSQL funktion, fordi den behandler SQL-kommandoer som forberedte sætninger, planlagt og udført sekventielt . Så hvert udsagn kan se objekter oprettet i tidligere udsagn.
Følgelig bliver sætninger, der aldrig besøges, aldrig engang planlagt - i modsætning til SQL-funktioner. Og eksekveringsplanen for sætninger kan cachelagres inden for samme session - også i modsætning til SQL-funktioner. Læs detaljer om plancaching i PL/pgSQL-funktioner i manualen her.
Hver tilgang har fordele for nogle brugssager. Yderligere læsning:
- Forskellen mellem sprog sql og sprog plpgsql i PostgreSQL-funktioner