web-dev-qa-db-fra.com

Différence entre language sql et language plpgsql dans les fonctions PostgreSQL

Suis très nouveau dans développement de base de données, j'ai donc quelques doutes concernant mon exemple suivant:

Fonction f1 () -langue sql

 create or replace function f1(istr  varchar) returns text as $$ 
 select 'hello! '::varchar || istr;
 $$ language sql;

Fonction f2 () -langage plpgsql

 create  or replace function f2(istr  varchar)
 returns text as $$ 
 begin select 'hello! '::varchar || istr; end;
 $$ language plpgsql;
  • Functions peuvent être appelés comme select f1('world') ou select f2('world').

  • Si j'appelle select f1('world') la sortie sera:

    `hello! world`
    
  • Et output pour select f2('world'):

    ERREUR: la requête n'a pas de destination pour les données de résultat ASTUCE: Si vous voulez ignorer les résultats d'un SELECT, utilisez PERFORM à la place . CONTEXTE: fonction PL/pgSQL f11 (variable de caractère) ligne 2 dans l'instruction SQL ****** Erreur ******

  • Je souhaite connaître la différence et dans quelles situations utiliser language sql ou language plpgsql.

Tout lien ou réponse utile concernant les fonctions sera très apprécié.

28
user3814846

Fonctions SQL

sont le meilleur choix:

  • Pour requêtes scalaires simples. Pas grand chose à planifier, il vaut mieux économiser les frais généraux.

  • Pour appels uniques par session. Rien à gagner de la mise en cache des plans et des instructions préparées que PL/pgSQL a à offrir. Voir ci-dessous.

  • Si elles sont généralement appelées dans le contexte de requêtes plus importantes et si elles sont assez simples pour être inlines .

  • Par manque de experience avec n’importe quel langage procédural tel que PL/pgSQL. Beaucoup connaissent bien le langage SQL et c'est à peu près tout ce dont vous avez besoin pour les fonctions SQL. Peu de gens peuvent en dire autant de PL/pgSQL.

  • Un code un peu plus court. Pas de frais généraux de bloc.

PL/pgSQL fonctions

sont le meilleur choix:

  • Lorsque vous avez besoin d'éléments procéduraux ou variables qui ne sont pas disponibles dans les fonctions SQL, évidemment.

  • Pour tout type de dynamic SQL, où vous construisez et EXECUTE instructions dynamiquement. Une attention particulière est nécessaire pour éviter l'injection SQL. Plus de détails:

  • Lorsque vous avez calculs, vous pouvez réutiliser à plusieurs endroits et vous ne pouvez pas étirer un CTE à cette fin. Dans une fonction SQL, vous n'avez pas de variables et seriez obligé de calculer à plusieurs reprises ou d'écrire dans une table. Cette réponse associée sur dba.SE contient côte à côte des exemples de code permettant de résoudre le même problème à l'aide d'une fonction SQL/d'une fonction plpgsql/d'une requête avec des CTE:

    Les assignations sont un peu plus chères que dans d'autres langages procéduraux. Adaptez un style de programmation qui n'utilise pas plus de tâches que nécessaire.

  • Lorsqu'une fonction ne peut pas être en ligne et est appelée à plusieurs reprises. Contrairement aux fonctions SQL, les plans de requête peuvent être mis en cache pour toutes les instructions SQL contenues dans une fonction PL/pgSQL ; ils sont traités comme instructions préparées, le plan est mis en cache pour les appels répétés au sein de la même session (si Postgres s'attend à ce que le plan mis en cache (générique) fonctionne mieux que la re-planification à chaque fois. sont généralement plus rapide après les deux premiers appels dans de tels cas. 

    Voici un fil sur pgsql-performance traitant de certains de ces éléments:
    Objet: Les fonctions pl/pgsql sont-elles plus performantes que celles de SQL?

  • Lorsque vous avez besoin de erreurs de recouvrement.

  • Pour les procédures trigger (qui ne sont que des fonctions).

  • Lorsque vous incluez des instructions DDL, modifiez les objets ou les catalogues système de manière pertinente pour les commandes suivantes, car toutes les instructions des fonctions SQL sont analysées en même temps, tandis que les fonctions PL/pgSQL planifient et exécutent chaque instruction de manière séquentielle (comme une instruction préparée). Voir:

Considérez également:


Pour être complet: pour réellement retour à partir d'une fonction PL/pgSQL, vous pouvez écrire:

CREATE FUNCTION f2(istr varchar)
  RETURNS text AS
$func$
BEGIN
   RETURN 'hello! ';  -- defaults to type text anyway
END
$func$ LANGUAGE plpgsql;

Il y a d'autres moyens:

41
Erwin Brandstetter

PL/PgSQL est un langage procédural spécifique à PostgreSQL basé sur SQL . Il contient des boucles, des variables, des erreurs/exceptions, etc. Tout le SQL n'est pas valide PL/PgSQL - comme vous l'avez découvert, vous ne pouvez pas utiliser SELECT sans INTO ou RETURN QUERY. PL/PgSQL peut également être utilisé dans des blocs DO pour des procédures uniques.

Les fonctions sql ne peuvent utiliser que du SQL pur, mais elles sont souvent plus efficaces et plus simples à écrire car vous n'avez pas besoin d'un bloc BEGIN ... END;, etc. Les fonctions SQL peuvent être en ligne, ce qui n'est pas vrai pour PL/PgSQL.

Les gens utilisent souvent PL/PgSQL où SQL pur serait suffisant, car ils sont habitués à penser de manière procédurale. Dans la plupart des cas, vous pensez probablement avoir besoin de PL/PgSQL. Les CTE récursifs, les requêtes latérales, etc. répondent généralement à la plupart des besoins.

Pour plus d'informations ... voir le manuel.

13
Craig Ringer

il suffit que la requête de sélection que vous avez écrite dans la fonction soit la valeur renvoyée:

 create  or replace function f2(istr  varchar)
 returns text as $$ 
 begin return(select 'hello! '::varchar || istr); end;
 $$ language plpgsql;
0
ZORRO_BLANCO