Déclarer une variable de type table en PL / pgSQL

8

Je me demande s'il existe un moyen de déclarer une variable de type table en PL / pgSQL pour contenir les résultats de la requête? Par exemple, comment puis-je exprimer quelque chose comme:

q1 = select * from foo;
q2 = select * from bar;
for t1 in q1:
  for t2 in q2:
    -- do something with t1 and t2

J'ai examiné la construction de retour suivante, mais cela ne semble pouvoir gérer que les valeurs de retour.

JRR
la source
2
PL / SQL => Oracle, PgPL / SQL => PostgreSQL. Avec lequel travaillez-vous?
Mat
@Mat: C'est PL / pgSQL , btw.
Erwin Brandstetter

Réponses:

12

Dans PostgreSQL , chaque nom de table sert automatiquement de nom de type pour le type de ligne (ou type composite ) - pas un type de table, il n'y a pas de "types de table" ou de "variables de table" dans Postgres ( mais il y a des tables typées ).
Vous pouvez donc simplement déclarer une variable de ce type dans PL/pgSQL.

CREATE FUNCTION foo()
 RETURNS void LANGUAGE plpgsql AS
$func$
DECLARE
  q1 foo;  -- "foo" ...
  q2 bar;  -- ... and "bar" are existing (visible) table names
BEGIN

FOR q1 IN 
   SELECT * from foo
LOOP
   FOR q2 IN 
      SELECT * from bar
   LOOP
       -- do something with q1 and q2
       -- since q1 and q2 are well known types, you can access columns
       -- with attribute notation. Like: q1.col1
   END LOOP;
END LOOP;

END
$func$

Une FORboucle fonctionne avec un curseur intégré. Il y a aussi des curseurs explicites dans plpgsql.

Vous pouvez également simplement déclarer des variables de type générique record. Il peut prendre n'importe quel type de ligne lors de l'attribution automatiquement. Mais des règles spéciales s'appliquent. Assurez-vous de suivre le lien et de lire le chapitre du manuel!

Bien qu'il soit souvent pratique de renvoyer la fonction SETOF <table name>, le retour SETOF recordn'est pas aussi pratique. Le système ne sait pas ce que la fonction renvoie de cette façon et vous devez ajouter une liste de définition de colonne à chaque appel. Ce qui est pénible. Détails sur les fonctions de table dans le manuel .

Cependant, il existe souvent des solutions plus efficaces avec du SQL simple. La boucle est une mesure de dernier recours, lorsque vous pouvez faire des choses en une seule analyse où vous auriez besoin de plusieurs analyses en SQL pur.

Erwin Brandstetter
la source
2
Notez également que si vous souhaitez renvoyer le type de table, vous pouvez simplement dire quelque chose commeCREATE FUNCTION footest() RETURNS SETOF foo LANGUAGE PLPGSQL AS $$...
Chris Travers
Pourquoi alors nous avons tous la caractéristique de "types composites" si nous pouvons créer des tables à la place, sans restrictions appliquées aux types composites (pas de contraintes, etc.)? La seule façon significative d'utiliser des types composites que je vois est de renvoyer quelques (ou plusieurs) paramètres à partir d'une fonction au lieu de créer une table entière pour cela.
SaneDeveloper