PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Perché le funzioni PL/pgSQL possono avere effetti collaterali, mentre le funzioni SQL no?

Hai messo in grassetto la frase chiave nel manuale:

L'intero corpo di una funzione SQL viene analizzato prima che venga eseguita.

Leggi anche su The Parser Stage nel manuale.

Si compone di due parti principali:il parser e il processo di trasformazione . Citando il manuale:

il processo di trasformazione prende l'albero restituito dal parser come input ed esegue l'interpretazione semantica necessaria per capire a quali tabelle, funzioni e operatori fa riferimento la query.

Se una funzione SQL contiene questi comandi:

CREATE TABLE foo (...);
INSERT INTO foo VALUES(...);

Entrambe le istruzioni sono pianificate praticamente contemporaneamente (sulla base della stessa istantanea dei cataloghi di sistema). Quindi, il INSERT non può vedere la tabella "foo" presumibilmente creata con il precedente CREATE comando. Ciò crea uno dei seguenti problemi :

  1. Se non ci sono altro tabella denominata "pippo" nel tuo search_patch (ancora), Postgres si lamenta durante il tentativo di creare la funzione:

    ERROR:  relation "foo" does not exist
    
  2. Se esiste già un'altra tabella denominata "foo" nel tuo search_patch (e non usi nomi di colonna in conflitto), Postgres pianificherà il INSERT sulla base di quella tabella preesistente. In genere ciò provoca un errore al momento dell'esecuzione , se alcuni valori causano conflitti nella tabella (errata!). Oppure, con un po' di sfortuna, potrebbe persino scrivere su quella tabella senza messaggi di errore! Bug molto subdolo.

Ciò non può accadere con un PL/pgSQL funzione, perché tratta i comandi SQL come istruzioni preparate, pianificate ed eseguite in sequenza . Quindi ogni istruzione può vedere gli oggetti creati nelle istruzioni precedenti.

Di conseguenza, le istruzioni che non vengono mai visitate non vengono nemmeno pianificate, a differenza delle funzioni SQL. E il piano di esecuzione per le istruzioni può essere memorizzato nella cache all'interno della stessa sessione, anche a differenza delle funzioni SQL. Leggi i dettagli sulla memorizzazione nella cache dei piani nelle funzioni PL/pgSQL nel manuale qui.
Ogni approccio presenta vantaggi per alcuni casi d'uso. Ulteriori letture:

  • Differenza tra linguaggio sql e linguaggio plpgsql nelle funzioni PostgreSQL