Les fonctions PL / PgSQL et plain SQL font toutes deux partie d'un ensemble d'outils plus large et doivent être considérées dans ce contexte. J'ai tendance à y penser en termes d'échelle de puissance ascendante assortie d'une complexité et d'un coût croissants, où vous devriez utiliser l'outil le plus simple qui fera bien le travail:
- Utilisez des vues lorsque cela est possible
- Lorsqu'une vue ne convient pas, utilisez une fonction SQL
- Lorsqu'une fonction SQL ne convient pas, utilisez PL / PgSQL.
- Lorsque PL / PgSQL est trop limité ou pas assez expressif, utilisez PL / Perl, PL / Python, PL / V8, PL / Java, ou quelle que soit votre préférence.
- ... et où aucun PL ne fera le travail, utilisez un programme externe et éventuellement
LISTEN
et NOTIFY
pour lui parler.
Très souvent, une vue est suffisante lorsque vous pensez qu'une fonction est nécessaire. Même si cela coûte extrêmement cher à SELECT
la vue entière, les WHERE
clauses de la requête faisant référence à la vue sont généralement poussées vers le bas dans la vue et peuvent entraîner des plans de requête très différents. J'ai souvent eu de grandes améliorations des performances de la conversion des fonctions SQL en vues.
La principale fois où vous constatez que vous ne pouvez pas utiliser une vue et que vous devez envisager une fonction SQL est lorsque:
- Des paramètres qui ne peuvent pas être exprimés comme de simples
WHERE
clauses sont nécessaires, comme un paramètre dans une WITH
expression
- Vous voulez une barrière de sécurité via une
SECURITY DEFINER
fonction, et les security_barrier
vues dans PostgreSQL 9.2 et supérieur ne sont pas suffisantes pour vos besoins;
- Vous avez besoin de paramètres qui ne sont pas poussés vers le bas dans les sous-clauses d'une vue par l'optimiseur et que vous souhaitez contrôler plus directement; ou
- Il y a beaucoup de paramètres ou il y a beaucoup de répétitions des paramètres, il est donc impossible d'écrire la requête sous forme de vue.
Pour la plupart de ces tâches, une simple fonction SQL fonctionne correctement et est souvent plus facile à lire que PL / PgSQL. Les fonctions SQL déclarées STABLE
ou IMMUTABLE
(et non également déclarées STRICT
ou SECURITY DEFINER
) peuvent également être insérées dans l'instruction appelante. Cela supprime la surcharge des appels de fonction et peut parfois entraîner d'énormes avantages en termes de performances lorsqu'une condition WHERE dans la fonction appelante est poussée dans la fonction SQL par l'optimiseur. Utilisez les fonctions SQL chaque fois qu'elles sont suffisantes pour la tâche.
La principale fois où les fonctions SQL ne feront pas le travail, c'est quand vous avez besoin de beaucoup de logique. Si / alors / sinon les opérations que vous ne pouvez pas exprimer sous forme d' CASE
instructions, beaucoup de réutilisation des résultats calculés, la création de valeurs à partir de morceaux, la gestion des erreurs, etc. PL / PgSQL est alors très pratique. Choisissez PL / PgSQL lorsque vous ne pouvez pas utiliser les fonctions SQL ou qu'elles ne conviennent pas, comme pour:
- SQL dynamique et DDL dynamique via l'
EXECUTE
instruction
- Lorsque vous souhaitez des
RAISE
erreurs / avertissements pour les journaux ou le client
- Lorsque vous avez besoin de la gestion des exceptions - vous pouvez intercepter et gérer les erreurs avec des
EXCEPTION
blocs au lieu de terminer la transaction en cas d'erreur
- Logique conditionnelle complexe qui ne correspond pas
CASE ... WHEN
très bien
- Beaucoup de réutilisation de valeurs calculées que vous ne pouvez pas adapter
WITH
et CTE
- Création d'enregistrements dynamiques
- Vous devez effectuer une action après avoir produit le jeu de résultats
Avec les expressions de table communes (CTE), en particulier les CTE inscriptibles et WITH RECURSIVE
je trouve que j'utilise PL / PgSQL beaucoup moins qu'auparavant parce que SQL est beaucoup plus expressif et puissant. J'utilise beaucoup plus les vues et les fonctions SQL simples. Il convient de se rappeler que les fonctions SQL simples peuvent contenir plusieurs instructions; la dernière instruction est le résultat de la fonction.