Pourquoi existe-t-il une différence de comportement entre l'utilisation d'une fonction de retour définie (SRF) dans la liste SELECT et l'utilisation de SRF dans la clause FROM?
Par exemple, pour un SRF simple renvoyant 2 lignes:
CREATE OR REPLACE FUNCTION gen_series(out integer, out int)
RETURNS SETOF record AS $$
SELECT 1,1
UNION
SELECT 2,2;
$$ LANGUAGE SQL;
SELECT gen_series();
renvoie deux lignes de colonne unique contenant chacune un enregistrement:
=> gen_series
------------
(1,1)
(2,2)
(2 rows)
Alors que SELECT * FROM gen_series();
renvoie deux lignes avec l'enregistrement développé:
=> column1 | column2
---------+---------
1 | 1
2 | 2
(2 rows)
Par comparaison, si le SRF renvoie une seule colonne, l'appel de SRF dans la clause SELECT ou FROM ne fait aucune différence. par exemple:
=> SELECT generate_series(1,2);
generate_series
-----------------
1
2
(2 rows)
=> SELECT * FROM generate_series(1,2);
generate_series
-----------------
1
2
(2 rows)
Mes questions sont:
Je ne vois pas très bien pourquoi dans le deuxième cas, le comportement SRF est différent du premier cas simplement parce que la table retournée a une seule colonne. Ce comportement est-il vraiment cohérent en termes de types, tuples et ensembles?
Quelle est la différence entre les deux cas qui conduit au comportement différent?
Les SRF peuvent être utilisés comme des tableaux comme indiqué ci-dessus, mais les tableaux peuvent-ils également être utilisés pour remplacer les SRF? par exemple
SELECT my_table;
Apparemment, cela ne peut pas être fait, mais pourquoi est-ce SELECT my_SRF();
possible, alors que ce
SELECT my_table;
n'est pas permis (en termes de relations et de mathématiques)?
SELECT my_table;
n'est pas une syntaxe valideRéponses:
Postgres traite différemment le cas simple. Plusieurs colonnes sont traitées comme du type composite (ligne de tableau), qui est uniquement décomposé
SELECT * FROM ...
, tandis qu'une seule colonne de type scalaire est traitée comme cela, sans encapsuleur de type composite ajouté. Produit doncSELECT my_SRF()
la même chose queSELECT * FROM my_SRF()
pour le cas simple. Le manuel sur les fonctions de table :Je suis d'accord que cela prête à confusion, et vous n'êtes pas le premier à être confus. (Considérez l'alternative, cependant: l'ajout d'un wrapper de type composite autour d'une seule colonne peut être encore plus déroutant.)
Mais pas aussi confus que ce qui se passe lorsque vous combinez plusieurs fonctions SRF dans la
SELECT
liste. Cela va changer avec Postgres 10 pour de bon, cependant:Le moyen sûr et moins déroutant pour l'un ou l'autre cas est de déplacer les fonctions SRF vers la
FROM
clause. Utilisez uneLATERAL
jointure si vous devez faire référence à des colonnes d'une autre table. Le manuel suggère:la source