Wie übergebe ich eine Zeile als Parameter an eine Postgres-Funktion?

9

Ich habe eine Funktion build_details (), die als einen ihrer Parameter eine einzelne Zeile / einen Datensatz aus einer anderen Tabelle verwendet.

Das möchte ich tun, aber es funktioniert nicht:

SELECT build_details(
    SELECT * FROM my_table LIMIT 1,
    1000,
    TRUE)

Ich möchte eine einzelne Zeile aus my_table nehmen und an die Funktion übergeben, damit sie ausgeführt werden kann. Wie rufe ich die Funktion vom Terminal mit einem Datensatz von my_table auf?

jase81
quelle

Antworten:

8

Das ist viel einfacher. Während man erwarten würde, dass es ...

SELECT build_details(my_table.*, 1000, TRUE) FROM my_table LIMIT 1;

... die eigentliche Syntax lautet:

SELECT build_details(my_table, 1000, TRUE) FROM my_table LIMIT 1;
Eduardo
quelle
Ich habe gerade unsere Antworten zusammengeführt und dieses Popup oben gesehen. Ich habe es beantwortet und nicht bemerkt, dass Ihre Antwort bereits das Zeilenobjekt verwendet, und ich wollte es nicht ganken. Du hast mich bis zum Anschlag geschlagen.
Evan Carroll
Warum um alles in der Welt hast du das getan?
Eduardo
1
@EvanCarrollQWERHJKL Ich habe keine Ahnung, was Sie versucht haben, indem Sie meine Antwort durch Ihre ersetzt haben, aber ich habe die Dinge einfach so zurückgesetzt, wie sie vor Ihrem Fummeln waren.
Eduardo
cool, ich werde dann einfach meine eigenen einreichen. =) Es ist im Grunde die gleiche Methode, außer erklärt.
Evan Carroll
6

Ich würde es so machen,

SELECT *
FROM my_table
CROSS JOIN LATERAL build_details( my_table, 1000, true )
LIMIT 1;

Sie können dies anhand einiger Beispieldaten unten sehen.

-- create some sample data,
CREATE TABLE foo(bar)
  AS VALUES (42::int), (7);

-- select a row object, representing every row in foo;
SELECT foo 
FROM foo;

Erstellen Sie eine Funktion, die den Zeilentypfoo a boolund an verwendet, inteinfach einen Hinweis auslöst und true zurückgibt.

CREATE FUNCTION build_details( myrow foo, j int, k bool )
RETURNS bool AS $$
  BEGIN
    RAISE NOTICE '%, %, %', myrow, j, k;
    RETURN true;
  END;
$$ LANGUAGE plpgsql;

Jetzt können wir die obige Syntax verwenden, indem wir das Zeilenobjekt übergeben, das eine Zeile in darstellt foo, zusammen mit zwei anderen Variablen an intund a bool.

SELECT *
FROM foo
CROSS JOIN LATERAL build_details(foo::foo, 1000, true);
NOTICE:  (42), 1000, t
NOTICE:  (7), 1000, t
 bar | build_details 
-----+---------------
  42 | t
   7 | t
(2 rows)

Sie können natürlich LIMITimmer noch Prädikate verwenden oder was auch immer Sie möchten.

Evan Carroll
quelle
1
Beachten Sie, dass dies SELECT * FROM foo, build_details(foo, 1000, true)eine Verknüpfung zur endgültigen Abfrage ist. Es führt eine implizite seitliche Verbindung durch.
Pbillen
1
Ich bin zufällig auf diese Antwort gestoßen, als ich herausgefunden habe, warum ich nicht einfach anrufen konnte select some_func(foo.*)..., um meine Zeile an die Funktion zu senden. Das Geheimnis war select some_func(foo::foo).... Vielen Dank!
Phil
@Phil Die Zeile ist bereits in die Tabelle eingegeben. Sie sollten dies nur benötigen, wenn Sie einen Zeilentyp in einen anderen Zeilentyp umwandeln möchten.
Evan Carroll
Das habe ich gehofft. Leider musste ich es explizit besetzen. Seltsam, aber in meinem speziellen Fall wahr.
Phil
3

Verwenden einer Unterauswahl zum erneuten Auswählen der Zeile

Das schien zu funktionieren:

SELECT * FROM public.build_details(
    (SELECT r.*::public.my_table FROM (TABLE public.my_table) r LIMIT 1),
    1000,
    TRUE);
jase81
quelle