Documentation PostgreSQL 8.0.25 | ||||
---|---|---|---|---|
Pr�c�dent | Arri�re rapide | Chapitre 35. PL/pgSQL - Langage de proc�dures SQL | Avance rapide | Suivant |
Plut�t que d'ex�cuter la totalit� d'une requ�te � la fois, il est possible de cr�er un curseur qui encapsule la requ�te, puis en lit le r�sultat quelques lignes � la fois. Une des raisons pour faire de la sorte est d'�viter les surcharges de m�moire quand le r�sultat contient un grand nombre de lignes (cependant, les utilisateurs PL/pgSQL n'ont g�n�ralement pas besoin de se pr�occuper de cela puisque les boucles FOR utilisent automatiquement un curseur en interne pour �viter les probl�mes de m�moire). Un usage plus int�ressant est de renvoyer une r�f�rence � un curseur qu'elle a cr��, permettant � l'appelant de lire les lignes. Ceci fournit un moyen efficace de renvoyer de grands ensembles de lignes � partir des fonctions.
Tous les acc�s aux curseurs dans PL/pgSQL se font par les variables curseur, qui sont toujours du type de donn�es sp�cial refcursor. Un des moyens de cr�er une variable curseur est de simplement la d�clarer comme une variable de type refcursor. Un autre moyen est d'utiliser la syntaxe de d�claration de curseur qui est en g�n�ral :
nom CURSOR [ ( arguments ) ] FOR requ�te ;
(FOR peut �tre remplac� par IS pour la compatibilit� avec Oracle). arguments, si sp�cifi�, est une liste de paires de nom type-de-donn�e qui d�finit les noms devant �tre remplac�s par les valeurs des param�tres dans la requ�te donn�e. La valeur effective � substituer pour ces noms sera sp�cifi�e plus tard lors de l'ouverture du curseur.
Quelques exemples :
DECLARE curs1 refcursor; curs2 CURSOR FOR SELECT * FROM tenk1; curs3 CURSOR (key integer) IS SELECT * FROM tenk1 WHERE unique1 = key;
Ces variables sont toutes trois du type de donn�es refcursor, mais la premi�re peut �tre utilis�es avec n'importe quelle requ�te, alors que la seconde a une requ�te compl�tement sp�cifi�e qui lui est d�j� li�e, et la derni�re est li�e � une requ�te param�tr�e. (key sera remplac�e par un param�tre de valeur enti�re lors de l'ouverture du curseur.) La variable curs1 est dite non li�e puisqu'elle n'est pas li�e a une requ�te particuli�re.
Avant qu'un curseur puisse �tre utilis� pour rapatrier des lignes, il doit �tre ouvert. (C'est l'action �quivalente de la commande SQL DECLARE CURSOR.) PL/pgSQL a trois formes pour l'instruction OPEN, dont deux utilisent des variables curseur non li�es et les autres utilisent une variable curseur li�e.
OPEN curseur_non_li� FOR SELECT ...;
La variable curseur est ouverte et re�oit la requ�te sp�cifi�e � ex�cuter. Le curseur ne peut pas �tre d�j� ouvert, et il doit avoir �t� d�clar� comme curseur non li�. (c'est � dire comme une simple variable refcursor). La requ�te SELECT est trait�e de la m�me fa�on que les autres instructionsSELECT dans PL/pgSQL : les noms de variables PL/pgSQL sont remplac�s, et le plan de requ�te est mis en cache pour une possible r�utilisation.
Exemple :
OPEN curs1 FOR SELECT * FROM foo WHERE key = mykey;
OPEN curseur_non_li� FOR EXECUTE cha�ne_requ�te;
La variable curseur est ouverte et re�oit la requ�te sp�cifi�e � ex�cuter. Le curseur ne peut pas �tre d�j� ouvert et il doit avoir �t� d�clar� comme curseur non-li� (c'est-�-dire comme une simple variable refcursor. La requ�te est sp�cifi�e comme une expression cha�ne de la m�me fa�on que dans une commande EXECUTE. Comme d'habitude, ceci donne assez de flexibilit� pour que la requ�te puisse changer d'une ex�cution � l'autre.
Exemple :
OPEN curs1 FOR EXECUTE 'SELECT * FROM ' || quote_ident($1);
OPEN curseur_li� [ ( arguments ) ];
Cette forme d'OPEN est utilis�e pour ouvrir une variable curseur � laquelle la requ�te est li�e au moment de la d�claration. Le curseur ne peut pas �tre d�j� ouvert. Une liste des expressions arguments doit appara�tre si et seulement si le curseur a �t� d�clar� comme acceptant des arguments. Ces valeurs seront remplac�es dans la requ�te. Le plan de requ�te pour un curseur li� est toujours consid�r� comme pouvant �tre mis en cache ; il n'y a pas d'�quivalent de la commande EXECUTE dans ce cas.
Exemples :
OPEN curs2; OPEN curs3(42);
Une fois qu'un curseur a �t� ouvert, il peut �tre manipul� gr�ce aux instructions d�crites ci-dessous.
Ces manipulations n'ont pas besoin de se d�rouler dans la m�me fonction que celle qui a ouvert le curseur. Vous pouvez renvoyer une valeur refcursor � partir d'une fonction et laisser l'appelant op�rer sur le curseur (d'un point de vue interne, une valeur refcursor est simplement la cha�ne de caract�res du nom d'un portail contenant la requ�te active pour le curseur. Ce nom peut �tre pass� � d'autres, assign� � d'autres variables refcursor et ainsi de suite, sans d�ranger le portail).
Tous les portails sont implicitement ferm�s � la fin de la transaction. C'est pourquoi une valeur refcursor est utilisable pour r�f�rencer un curseur ouvert seulement jusqu'� la fin de la transaction.
FETCH curseur INTO cible;
FETCH rapatrie le rang suivant depuis le curseur dans une cible, qui peut �tre une variable ligne, une variable record ou une liste de simples variables s�par�es d'une virgule, exactement comme SELECT INTO. Comme pour SELECT INTO, la variable sp�ciale FOUND peut �tre v�rifi�e pour voir si une ligne a �t� obtenue ou pas.
Exemple :
FETCH curs1 INTO var_ligne; FETCH curs2 INTO foo, bar, baz;
CLOSE curseur;
CLOSE ferme le portail sous-tendant un curseur ouvert. Ceci peut �tre utilis� pour lib�rer des ressources avant la fin de la transaction ou de lib�rer la variable curseur pour pouvoir la r�ouvrir.
Exemple :
CLOSE curs1;
Les fonctions PL/pgSQL peuvent renvoyer des curseurs � l'appelant. Ceci est utile pour renvoyer plusieurs lignes ou colonnes, sp�cialement avec des ensembles de r�sultats tr�s grands. Pour cela, la fonction ouvre le curseur et renvoie le nom du curseur � l'appelant (ou simplement ouvre le curseur en utilisant un nom de portail sp�cifi� par ou autrement connu par l'appelant). L'appelant peut alors r�cup�rer les lignes � partir du curseur. Le curseur peut �tre ferm� par l'appelant ou il sera ferm� automatiquement � la fin de la transaction.
Le nom du portail utilis� pour un curseur peut �tre sp�cifi� par le d�veloppeur ou peut �tre g�n�r� automatiquement. Pour sp�cifier un nom de portail, affectez simplement une cha�ne � la variable refcursor avant de l'ouvrir. La valeur de la variable refcursor sera utilis�e par OPEN comme nom du portail sous-jacent. N�anmoins, si la variable refcursor est NULL, OPEN g�n�re automatiquement un nom qui n'entre pas en conflit avec tout portail existant et l'affecte � la variable refcursor.
Note�: Une variable curseur avec limites est initialis�e avec la valeur de la cha�ne repr�sentant son nom, de fa�on � ce que le nom du portail soit identique au nom de la variable curseur, sauf si le d�veloppeur le surcharge par affectation avant d'ouvrir le curseur. Mais, une variable curseur sans limite aura par d�faut la valeur NULL, dont il recevra un nom unique g�n�r� automatiquement sauf s'il est surcharg�.
L'exemple suivant montre une fa�on de fournir un nom de curseur par l'appelant :
CREATE TABLE test (col text); INSERT INTO test VALUES ('123'); CREATE FUNCTION fonction_reference(refcursor) RETURNS refcursor AS ' BEGIN OPEN $1 FOR SELECT col FROM test; RETURN $1; END; ' LANGUAGE plpgsql; BEGIN; SELECT fonction_reference('curseur_fonction'); FETCH ALL IN curseur_fonction; COMMIT;
L'exemple suivant utilise la g�n�ration automatique du nom du curseur :
CREATE FUNCTION fonction_reference2() RETURNS refcursor AS ' DECLARE ref refcursor; BEGIN OPEN ref FOR SELECT col FROM test; RETURN ref; END; ' LANGUAGE plpgsql; BEGIN; SELECT fonction_reference2(); fonction_reference2 -------------------------- <unnamed cursor 1> (1 row) FETCH ALL IN "<unnamed cursor 1>"; COMMIT;
L'exemple suivant montre une fa�on de renvoyer plusieurs curseurs � une seule fonction :
CREATE FUNCTION ma_fonction(refcursor, refcursor) RETURNS SETOF refcursor AS $$ BEGIN OPEN $1 FOR SELECT * FROM table_1; RETURN NEXT $1; OPEN $2 FOR SELECT * FROM table_2; RETURN NEXT $2; RETURN; END; $$ LANGUAGE plpgsql; -- doit �tre dans une transaction pour utiliser les curseurs. BEGIN; SELECT * FROM ma_fonction('a', 'b'); FETCH ALL FROM a; FETCH ALL FROM b; COMMIT;
Pr�c�dent | Sommaire | Suivant |
Structures de contr�le | Niveau sup�rieur | Erreurs et Messages |