Toutes les variables utilisées dans un bloc doivent �tre déclarées dans la section déclaration du bloc. Les seules exceptions sont que la variable de boucle d'une boucle FOR effectuant une itération sur des valeurs enti�res est automatiquement déclarée comme variable enti�re (type integer), et de la m�me fa�on une variable de boucle FOR effectuant une itération sur le résultat d'un curseur est automatiquement déclarée comme variable de type record.
Les variables PL/pgSQL peuvent �tre de n'importe quel type de données tels que integer, varchar et char.
Quelques exemples de déclaration de variables :
id_utilisateur integer; quantité numeric(5); url varchar; ma_ligne nom_table%ROWTYPE; mon_champ nom_table.nom_colonne%TYPE; une_ligne RECORD;
La syntaxe générale d'une déclaration de variable est :
nom [ CONSTANT ] type [ COLLATE nom_collationnement ] [ NOT NULL ] [ { DEFAULT | := } expression ];
La clause DEFAULT, si indiquée, spécifie la valeur initiale affectée � la variable quand on entre dans le bloc. Si la clause DEFAULT n'est pas indiquée, la variable est initialisée � la valeur SQL NULL. L'option CONSTANT emp�che la modification de la variable apr�s initialisation, de sorte que sa valeur reste constante pour la durée du bloc. L'option COLLATE indique le collationnement � utiliser pour la variable (voir Section 40.3.6, � Collationnement des variables PL/pgSQL �). Si NOT NULL est spécifié, l'affectation d'une valeur NULL aboutira � une erreur d'exécution. Les valeurs par défaut de toutes les variables déclarées NOT NULL doivent �tre précisées, donc non NULL.
La valeur par défaut d'une variable est évaluée et affectée � la variable � chaque entrée du bloc (pas seulement une fois lors de l'appel de la fonction). Ainsi, par exemple, l'affectation de now() � une variable de type timestamp donnera � la variable l'heure de l'appel de la fonction courante, et non l'heure au moment o� la fonction a été précompilée.
Exemples :
quantité integer DEFAULT 32; url varchar := 'http://mysite.com'; id_utilisateur CONSTANT integer := 10;
Les param�tres passés aux fonctions sont nommés par les identifiants $1, $2, etc. �ventuellement, des alias peuvent �tre déclarés pour les noms de param�tres de type $n afin d'améliorer la lisibilité. L'alias ou l'identifiant numérique peuvent �tre utilisés indifféremment pour se référer � la valeur du param�tre.
Il existe deux fa�ons de créer un alias. La fa�on préférée est de donner un nom au param�tre dans la commande CREATE FUNCTION, par exemple :
CREATE FUNCTION taxe_ventes(sous_total real) RETURNS real AS $$ BEGIN RETURN sous_total * 0.06; END; $$ LANGUAGE plpgsql;
L'autre fa�on, la seule disponible pour les versions antérieures � PostgreSQL™ 8.0, est de déclarer explicitement un alias en utilisant la syntaxe de déclaration :
nom ALIAS FOR $n;
Le m�me exemple dans ce style ressemble � ceci :
CREATE FUNCTION taxe_ventes(real) RETURNS real AS $$ DECLARE sous_total ALIAS FOR $1; BEGIN RETURN sous_total * 0.06; END; $$ LANGUAGE plpgsql;
Ces deux exemples ne sont pas compl�tement identiques. Dans le premier cas, sous_total peut �tre référencé comme taxe_ventes.sous_total, alors que ce n'est pas possible dans le second cas. (Si nous avions attaché un label au bloc interne, sous_total aurait pu utiliser ce label � la place.)
Quelques exemples de plus :
CREATE FUNCTION instr(varchar, integer) RETURNS integer AS $$ DECLARE v_string ALIAS FOR $1; index ALIAS FOR $2; BEGIN -- quelques traitements utilisant ici v_string et index END; $$ LANGUAGE plpgsql; CREATE FUNCTION concat_champs_selectionnes(in_t un_nom_de_table) RETURNS text AS $$ BEGIN RETURN in_t.f1 || in_t.f3 || in_t.f5 || in_t.f7; END; $$ LANGUAGE plpgsql;
Quand une fonction PL/pgSQL est déclarée avec des param�tres en sortie, ces derniers se voient attribués les noms $n et des alias optionnels de la m�me fa�on que les param�tres en entrée. Un param�tre en sortie est une variable qui commence avec la valeur NULL ; il devrait se voir attribuer une valeur lors de l'exécution de la fonction. La valeur finale du param�tre est ce qui est renvoyée. Par exemple, l'exemple taxe_ventes peut s'écrire de cette fa�on :
CREATE FUNCTION taxe_ventes(sous_total real, OUT taxe real) AS $$ BEGIN taxe := sous_total * 0.06; END; $$ LANGUAGE plpgsql;
Notez que nous avons omis RETURNS real. Nous aurions pu l'inclure mais cela aurait été redondant.
Les param�tres en sortie sont encore plus utiles lors du retour de plusieurs valeurs. Un exemple trivial est :
CREATE FUNCTION somme_n_produits(x int, y int, OUT somme int, OUT produit int) AS $$ BEGIN somme := x + y; produit := x * y; END; $$ LANGUAGE plpgsql;
D'apr�s ce qui a été vu dans la Section 35.4.4, � Fonctions SQL avec des param�tres en sortie �, ceci crée réellement un type d'enregistrement anonyme pour les résultats de la fonction. Si une clause RETURNS est donnée, elle doit spécifier RETURNS record.
Voici une autre fa�on de déclarer une fonction PL/pgSQL, cette fois avec RETURNS TABLE :
CREATE FUNCTION extended_sales(p_itemno int) RETURNS TABLE(quantity int, total numeric) AS $$ BEGIN RETURN QUERY SELECT quantity, quantity * price FROM sales WHERE itemno = p_itemno; END; $$ LANGUAGE plpgsql;
C'est exactement équivalent � déclarer un ou plusieurs param�tres OUT et � spécifier RETURNS SETOF un_type.
Lorsque le type de retour d'une fonction PL/pgSQL est déclaré comme type polymorphe (anyelement, anyarray, anynonarray, anyenum et anyrange), un param�tre spécial $0 est créé. Son type de donnée est le type effectif de retour de la fonction, déduit d'apr�s les types en entrée (voir la Section 35.2.5, � Types et fonctions polymorphes �). Ceci permet � la fonction d'accéder � son type de retour réel comme on le voit ici avec la Section 40.3.3, � Copie de types �. $0 est initialisé � NULL et peut �tre modifié par la fonction, de sorte qu'il peut �tre utilisé pour contenir la variable de retour si besoin est, bien que cela ne soit pas requis. On peut aussi donner un alias � $0. Par exemple, cette fonction s'exécute comme un opérateur + pour n'importe quel type de données :
CREATE FUNCTION ajoute_trois_valeurs(v1 anyelement, v2 anyelement, v3 anyelement) RETURNS anyelement AS $$ DECLARE resultat ALIAS FOR $0; BEGIN resultat := v1 + v2 + v3; RETURN resultat; END; $$ LANGUAGE plpgsql;
Le m�me effet peut �tre obtenu en déclarant un ou plusieurs param�tres polymorphes en sortie de types. Dans ce cas, le param�tre spécial $0 n'est pas utilisé ; les param�tres en sortie servent ce m�me but. Par exemple :
CREATE FUNCTION ajoute_trois_valeurs(v1 anyelement, v2 anyelement, v3 anyelement, OUT somme anyelement) AS $$ BEGIN somme := v1 + v2 + v3; END; $$ LANGUAGE plpgsql;
nouveaunom ALIAS FOR anciennom;
La syntaxe ALIAS est plus générale que la section précédente pourrait faire croire : vous pouvez déclarer un alias pour n'importe quelle variable et pas seulement des param�tres de fonction. L'utilisation principale de cette instruction est l'attribution d'un autre nom aux variables aux noms prédéterminés, telles que NEW ou OLD au sein d'une procédure trigger.
Exemples:
DECLARE anterieur ALIAS FOR old; misajour ALIAS FOR new;
ALIAS créant deux mani�res différentes de nommer le m�me objet, son utilisation � outrance peut préter � confusion. Il vaut mieux ne l'utiliser uniquement pour se passer des noms prédéterminés.
variable%TYPE
%TYPE fournit le type de données d'une variable ou d'une colonne de table. Vous pouvez l'utiliser pour déclarer des variables qui contiendront des valeurs de base de données. Par exemple, disons que vous avez une colonne nommée id_utilisateur dans votre table utilisateurs. Pour déclarer une variable du m�me type de données que utilisateurs.id_utilisateur, vous pouvez écrire :
id_utilisateur utilisateurs.id_utilisateur%TYPE;
En utilisant %TYPE vous n'avez pas besoin de conna�tre le type de données de la structure � laquelle vous faites référence et, plus important, si le type de données de l'objet référencé change dans le futur (par exemple : vous changez le type de id_utilisateur de integer � real), vous pouvez ne pas avoir besoin de changer votre définition de fonction.
%TYPE est particuli�rement utile dans le cas de fonctions polymorphes puisque les types de données nécessaires aux variables internes peuvent changer d'un appel � l'autre. Des variables appropriées peuvent �tre créées en appliquant %TYPE aux arguments de la fonction ou � la variable fictive de résultat.
nom nom_table%ROWTYPE; nom nom_type_composite;
Une variable de type composite est appelée variable ligne (ou variable row-type). Une telle variable peut contenir une ligne enti�re de résultat de requ�te SELECT ou FOR, du moment que l'ensemble de colonnes de la requ�te correspond au type déclaré de la variable. Les champs individuels de la valeur row sont accessibles en utilisant la notation pointée, par exemple varligne.champ.
Une variable ligne peut �tre déclarée de fa�on � avoir le m�me type que les lignes d'une table ou d'une vue existante, en utilisant la notation nom_table%ROWTYPE. Elle peut aussi �tre déclarée en donnant un nom de type composite. Chaque table ayant un type de données associé du m�me nom, il importe peu dans PostgreSQL™ que vous écriviez %ROWTYPE ou pas. Cependant, la forme utilisant %ROWTYPE est plus portable.
Les param�tres d'une fonction peuvent �tre des types composites (lignes compl�tes de tables). Dans ce cas, l'identifiant correspondant $n sera une variable ligne � partir de laquelle les champs peuvent �tre sélectionnés avec la notation pointée, par exemple $1.id_utilisateur.
Seules les colonnes définies par l'utilisateur sont accessibles dans une variable de type ligne, et non l'OID ou d'autres colonnes syst�mes (parce que la ligne pourrait �tre issue d'une vue). Les champs du type ligne héritent des tailles des champs de la table ou de leur précision pour les types de données tels que char(n).
Voici un exemple d'utilisation des types composites. table1 et table2 sont des tables ayant au moins les champs mentionnés :
CREATE FUNCTION assemble_champs(t_ligne table1) RETURNS text AS $$ DECLARE t2_ligne table2%ROWTYPE; BEGIN SELECT * INTO t2_ligne FROM table2 WHERE ... ; RETURN t_ligne.f1 || t2_ligne.f3 || t_ligne.f5 || t2_ligne.f7; END; $$ LANGUAGE plpgsql; SELECT assemble_champs(t.*) FROM table1 t WHERE ... ;
nom RECORD;
Les variables record sont similaires aux variables de type ligne mais n'ont pas de structure prédéfinie. Elles empruntent la structure effective de type ligne de la ligne � laquelle elles sont affectées durant une commande SELECT ou FOR. La sous-structure d'une variable record peut changer � chaque fois qu'on l'affecte. Une conséquence de cela est qu'elle n'a pas de sous-structure jusqu'� ce qu'elle ait été affectée, et toutes les tentatives pour accéder � un de ses champs entra�nent une erreur d'exécution.
Notez que RECORD n'est pas un vrai type de données mais seulement un param�tre fictif (placeholder). Il faut aussi réaliser que lorsqu'une fonction PL/pgSQL est déclarée renvoyer un type record, il ne s'agit pas tout � fait du m�me concept qu'une variable record, m�me si une telle fonction peut aussi utiliser une variable record pour contenir son résultat. Dans les deux cas, la structure réelle de la ligne n'est pas connue quand la fonction est écrite mais, dans le cas d'une fonction renvoyant un type record, la structure réelle est déterminée quand la requ�te appelante est analysée, alors qu'une variable record peut changer sa structure de ligne � la volée.
Quand une fonction PL/pgSQL a un ou plusieurs param�tres dont le type de données est collationnable, un collationnement est identifié pour chaque appel de fonction dépendant des collationnements affectés aux arguments réels, comme décrit dans Section 22.2, � Support des collations �. Si un collationnement est identifié avec succ�s (autrement dit, qu'il n'y a pas de conflit de collationnements implicites parmi les arguments), alors tous les param�tres collationnables sont traités comme ayant un collationnement implicite. Ceci affectera le comportement des opérations sensibles au collationnement dans la fonction. Par exemple, avec cette fonction
CREATE FUNCTION plus_petit_que(a text, b text) RETURNS boolean AS $$ BEGIN RETURN a < b; END; $$ LANGUAGE plpgsql; SELECT plus_petit_que(champ_text_1, champ_text_2) FROM table1; SELECT plus_petit_que(champ_text_1, champ_text_2 COLLATE "C") FROM table1;
La premi�re utilisation de less_than utilisera le collationnement par défaut de champ_text_1 et de champ_text_2 pour la comparaison alors que la seconde utilisation prendra le collationnement C.
De plus, le collationnement identifié est aussi considéré comme le collationnement de toute variable locale de type collationnable. Du coup, cette procédure stockée ne fonctionnera pas différemment de celle-ci :
CREATE FUNCTION plus_petit_que(a text, b text) RETURNS boolean AS $$ DECLARE local_a text := a; local_b text := b; BEGIN RETURN local_a < local_b; END; $$ LANGUAGE plpgsql;
S'il n'y a pas de param�tres pour les types de données collationnables ou qu'aucun collationnement commun ne peut �tre identifié pour eux, alors les param�tres et les variables locales utilisent le collationnement par défaut de leur type de données (qui est habituellement le collationnement par défaut de la base de données mais qui pourrait �tre différent pour les variables des types domaines).
Une variable locale d'un type de données collationnable peut avoir un collationnement différent qui lui est associé en incluant l'option COLLATE dans sa déclaration, par exemple
DECLARE local_a text COLLATE "en_US";
Cette option surcharge le collationnement qui serait normalement donné � la variable d'apr�s les r�gles ci-dessus.
De plus, les clauses COLLATE explicites peuvent �tre écrites � l'intérieur d'une fonction si forcer l'utilisation d'un collationnement particulier est souhaité pour une opération particuli�re. Par exemple,
CREATE FUNCTION plus_petit_que_c(a text, b text) RETURNS boolean AS $$ BEGIN RETURN a < b COLLATE "C"; END; $$ LANGUAGE plpgsql;
Ceci surcharge les collationnements associés avec les colonnes de la table, les param�tres ou la variables locales utilisées dans l'expression, comme cela arriverait dans une commande SQL simple.