PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Pourquoi les fonctions PL/pgSQL peuvent-elles avoir des effets secondaires, alors que les fonctions SQL ne le peuvent pas ?

Vous avez vous-même mis en gras la phrase clé du manuel :

Le corps entier d'une fonction SQL est analysé avant que l'une d'elle ne soit exécutée.

Lisez également à propos de L'étape de l'analyseur dans le manuel.

Il se compose de deux parties principales :l'analyseur et le processus de transformation . Citant le manuel :

le processus de transformation prend l'arbre renvoyé par l'analyseur en entrée et effectue l'interprétation sémantique nécessaire pour comprendre quelles tables, fonctions et opérateurs sont référencés par la requête.

Si une fonction SQL contient ces commandes :

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

Les deux déclarations sont planifiées pratiquement en même temps (sur la base du même instantané des catalogues système). Par conséquent, le INSERT ne peut pas voir la table "foo" vraisemblablement créée avec le précédent CREATE commande. Cela crée l'un des problèmes suivants :

  1. S'il n'y a pas d'autre table nommée "foo" dans votre search_patch (encore), Postgres se plaint en essayant de créer la fonction :

    ERROR:  relation "foo" does not exist
    
  2. Si une autre table nommée "foo" existe déjà dans votre search_patch (et vous n'utilisez pas de noms de colonnes en conflit), Postgres planifiera le INSERT basé sur cette table préexistante. Cela entraîne généralement une erreur au moment de l'exécution , si des valeurs provoquent des conflits dans la (mauvaise !) table. Ou, avec un peu de malchance, il pourrait même écrire dans cette table sans message d'erreur ! Bug très sournois.

Cela ne peut pas arriver avec un PL/pgSQL fonction, car elle traite les commandes SQL comme des instructions préparées, planifiées et exécutées séquentiellement . Ainsi, chaque instruction peut voir les objets créés dans les instructions précédentes.

Par conséquent, les instructions qui ne sont jamais visitées ne sont même jamais planifiées - contrairement aux fonctions SQL. Et le plan d'exécution des instructions peut être mis en cache dans la même session, contrairement aux fonctions SQL. Lisez les détails sur la mise en cache du plan dans les fonctions PL/pgSQL dans le manuel ici.
Chaque approche présente des avantages pour certains cas d'utilisation. Lectures complémentaires :

  • Différence entre le langage sql et le langage plpgsql dans les fonctions PostgreSQL