J'utilise Postgresql 9.1, avec Ubuntu 12.04.
Inspiré par la réponse de Craig à ma question Enchaînement de type setof ou un enregistrement setof je pensais aller bien à l' utilisation return query
, setof record
et un générateur de série dans cette fonction plpgsql:
create or replace function compute_all_pair_by_craig(id_obj bigint)
returns setof record as $$
begin
return query select o.id, generate_series(0,o.value) from m_obj as o;
end;
$$ language plpgsql;
Pendant l'exécution, j'obtiens l'erreur:
ERROR: set_valued function called in context that cannot accept a set
Qu'est-ce qui ne va pas ? Contrairement à Craig, je dis à la fonction de revenir setof record
.
Je peux réaliser quelque chose qui fonctionne exactement comme Craig, c'est-à-dire en définissant un type create type pair_id_value as (idx bigint, value integer)
et que ma fonction plpgsql renvoie a setof of pair_id_value
au lieu de a setof record
.
Mais même avec cette solution de travail, je ne comprends toujours pas pourquoi select id, generate_series(0,13)
seul retournera un résultat dans deux colonnes ... et au contraire appeler la fonction (retourne setof pair_id_value) avec return query select id, generate_series(0,my_obj.value) from my_obj
retournera un résultat dans une seule colonne dont le champ ressemble ce "(123123,0)" "(123123,1)" "(123123,2)" (3 lignes) qui sont évidemment des tuples.
Est-ce un cas où une table temporaire doit / doit être créée?
la source
BEGIN
et un manquant après leRETURN QUERY
. Après avoir corrigé ces erreurs, je confirme l'erreur lors du retourrecord
; expliquera en réponse.Réponses:
Le message d'erreur n'est pas très utile:
mais si vous reformulez la requête pour l'appeler comme une fonction de retour de jeu appropriée, vous verrez le vrai problème:
Si vous utilisez
SETOF RECORD
sansOUT
liste de paramètres, vous devez spécifier les résultats dans l'instruction d'appel, par exemple:Cependant, il est préférable d'utiliser des paramètres
RETURNS TABLE
ouOUT
. Avec l'ancienne syntaxe, votre fonction serait:Cela peut être appelé dans le contexte de la liste SELECT et peut être utilisé sans créer explicitement de type ni spécifier la structure des résultats sur le site d'appel.
En ce qui concerne la seconde moitié de la question, ce qui se passe, c'est que le premier cas spécifie deux colonnes distinctes dans une liste SELECT, tandis que la seconde renvoie un seul composite. Il ne s'agit en fait pas de la façon dont vous renvoyez le résultat, mais de la façon dont vous appelez la fonction. Si nous créons l'exemple de fonction:
Vous verrez la différence dans les deux façons d'appeler une fonction de retour d'ensemble - dans la
SELECT
liste, une extension non standard spécifique à PostgreSQL avec un comportement original:ou sous forme de tableau de manière plus standard:
la source
returns table
.