PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Wie übergebe ich einen Tabellenparameter an diese Funktion?

Alles in Postgres 9.4 getestet .

Postgres hat einige Schwachstellen in der Syntax für die Behandlung von ROW-Typen. Sie können nicht direkt aus einer Tabelle (Alias) umwandeln:

SELECT w::waypoint FROM waypoints w;

Die Lösung ist nur einen Schritt entfernt:Zeile in eine Unterabfrage zerlegen, dann funktioniert der Cast. Auf diese Weise werden Spaltenwerte zerlegt und direkt in den neuen Typ verpackt, ohne in text umgewandelt zu werden und zurück. Es ist nicht erforderlich, alle Spalten einzeln aufzulisten, und Sie müssen auch keine benutzerdefinierte Umwandlung erstellen:

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

Oder kürzer:

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

Oder noch kürzer:

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

SQL-Fiddle

Das ist kürzer und schneller, in einem Schnelltest mit 30.000 Zeilen und einfachen Typen 10x schneller als in text umzuwandeln und zurück. Wenn Sie (großes) jsonb haben Spalten oder jeden komplexen Typ (teure Konvertierung nach/von text ), wird der Unterschied noch viel größer sein.

Noch wichtiger, Sie brauchen nicht ein weiterer benutzerdefinierter Verbundtyp (ROW). Jede Tabelle hat ihre Zeile bereits automatisch als Typ definiert. Verwenden Sie einfach den vorhandenen Typ waypoints statt waypoint (Wenn überhaupt möglich). Dann brauchen Sie nur noch:

SELECT w FROM waypoints w;

Oder für Ihr Beispiel:

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

Nebenbei:

  • Eine Tabelle hat keine "Argumente", sondern Spalten.
  • Du bist nicht Übergabe eines table parameter to this function , sondern ein Zeilenwert . So übergeben Sie eine Tabelle nach Namen:

    Sie können in Postgres nicht direkt eine ganze Tabelle als Parameter übergeben, es gibt keine Tabellenvariablen. Sie würden dafür einen Cursor oder eine temporäre Tabelle verwenden.

Funktion

Ihre Funktion hat eine ungültige Typdeklaration und ist unnötig komplex. Ich bezweifle ernsthaft, dass Sie eine Ansicht erstellen möchten:

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 ist keine gültige Syntax, mit text[] stattdessen ein Array von text zu deklarieren .

Verwenden Sie lieber nicht den Tabellen-/Typnamen waypoints als Funktionsparametername, was Sie für verwirrende Fehler öffnet.

Oder verwenden Sie einfach eine einfache SQL-Funktion, wenn Ihr Fall so einfach ist wie gezeigt:

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

Zitieren Sie nicht den Namen der Sprache. Es ist eine Kennung.