PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Comment passer un paramètre de table à cette fonction ?

Tout a été testé dans Postgres 9.4 .

Postgres a quelques points faibles dans la syntaxe pour gérer les types ROW. Vous ne pouvez pas caster directement à partir d'une table (alias) :

SELECT w::waypoint FROM waypoints w;

La solution n'est qu'à une étape :décomposer la ligne en une sous-requête, puis le cast fonctionne. De cette façon, les valeurs de colonne sont décomposées et enveloppées directement dans le nouveau type, sans conversion en text et retour. Pas besoin de lister toutes les colonnes individuellement et vous n'avez pas non plus besoin de créer une distribution personnalisée :

SELECT (w.*)::waypoint FROM (SELECT * FROM waypoints) w;

Ou plus court :

SELECT w.*::waypoint FROM (TABLE waypoints) w;

Ou plus court, encore :

SELECT w::waypoint FROM (TABLE waypoints) w;

SQL Fiddle

C'est plus court et plus rapide, dans un test rapide avec 30 000 lignes et des types simples 10 fois plus rapide que de convertir en text et retour. Si vous avez (gros) jsonb colonnes ou tout type complexe (conversion coûteuse vers/depuis le text ), la différence sera encore bien plus grande.

Plus important encore, vous n'avez pas besoin un autre type composite personnalisé (ROW). Chaque table a déjà sa ligne définie comme type automatiquement. Utilisez simplement le type existant waypoints au lieu de waypoint (Si tout est possible). Alors tout ce dont vous avez besoin est :

SELECT w FROM waypoints w;

Ou, pour votre exemple :

SELECT everything(t) FROM temp t;  -- using type waypoints
SELECT everything(t::waypoint) FROM (TABLE temp) t;  -- using type waypoint

En plus :

  • Une table n'a pas d'"arguments" mais des colonnes.
  • Vous n'êtes pas passer un table parameter to this function , mais plutôt une valeur de ligne . C'est ainsi que vous passez une table par son nom :

    Vous ne pouvez pas "passer une table entière" comme paramètre directement dans Postgres, il n'y a pas de variables de table. Vous utiliseriez un curseur ou une table temporaire pour cela.

Fonction

Votre fonction a une déclaration de type non valide et est inutilement complexe. Je doute sérieusement que vous souhaitiez créer une vue :

CREATE FUNCTION everything(_wp waypoint)  -- or use type waypoints
  RETURNS TABLE(node int, xy text[]) AS
$func$
BEGIN
   RETURN QUERY
   SELECT ...
END
$func$ LANGUAGE plpgsql;

text array n'est pas une syntaxe valide, en utilisant text[] à la place de déclarer un tableau de text .

Plutôt ne pas utiliser le nom de table/type waypoints comme nom de paramètre de fonction, cela vous ouvre la porte à des erreurs déroutantes.

Ou utilisez simplement une simple fonction SQL si votre cas est aussi simple que démontré :

CREATE FUNCTION everything(_wp waypoint)  -- or use type waypoints
  RETURNS TABLE(node int, xy text[]) AS
$func$
   SELECT ...
$func$ LANGUAGE sql;

Ne citez pas le nom de la langue. C'est un identifiant.