2016-04-16 11 views
1

Ich erstelle dynamisch eine Abfrage in einer plpgsql-Funktion, die eine Quellentabelle als eingehende Variable akzeptiert. Ich möchte die Ergebnisse der erstellten SELECT-Anweisung zurückgeben, die Aggregationen für die angegebene Tabelle durchführt und Ergebnisse dieser Tabelle zurückgibt.Dynamische Definition zurückkehrender Zeilentypen basierend auf einer übergebenen gegebenen Tabelle in plpgsql?

jedoch im Moment erhalte ich folgende Fehlermeldung:

********** Error **********

ERROR: a column definition list is required for functions returning "record" SQL state: 42601

So sieht es aus wie ich Spaltentypen der Plattenreihe ich zurückkehren will definieren müssen.

I found this answer Hier können Sie die Tabellentypdeklaration umgehen, indem Sie die Tabelle angeben, zu der die resultierende Zeile passt.

RETURNS SETOF some_existing_table 

aber in meinem Fall, da die Tabelle, deren Spaltentypen Ich möchte die Funktion übergeben wird, übereinstimmen, ich weiß nicht, die Tabelle, bis ich die Variablen übergeben manipulieren kann (nach DECLARE/BEGIN).

Idealerweise möchte ich die Abfrageergebnisse (mehrere Zeilen) der Aggregationsabfrage, die ich innerhalb der Funktion erstellt habe, zurückgeben. Gibt es eine Möglichkeit, Ergebnisrückgabetypen basierend auf einer bekannten Tabelle dynamisch innerhalb der Funktion zu definieren?

Antwort

2

Is there a way to define result row return types based on a known table dynamically within the function?

Wenn von „basierend auf einer bekannten Tabelle“ Sie „genau wie eine bekannte Tabelle“ bedeuten, dann ja.

SQL ist eine streng typisierte Sprache und Funktionen müssen mit einem gut definierten Rückgabetyp erstellt werden. Sie können auf anonyme Datensätze wie Sie offensichtlich (mit RETURNS SETOF record) fallen, aber dann müssen Sie eine Spalte Definitionsliste für jeden Anruf hinzufügen, wie die Fehlermeldung Ihnen sagt. Etwas wie:

SELECT * 
FROM my_function('foo') AS foo (
      colum_name1 integer -- name and data type for every column 
     , colum_name2 text 
     , colum_name3 real); 

Und das ist kaum dynamisch.

Ihre Frage lässt Raum für Interpretation, aber „basiert auf einer bekannten Tabelle“ würde bedeuten, dass eine polymorphe Funktion könnte den Trick tun. Der Rückgabetyp kann dynamisch auf jedem registrierten Zeilentyp basieren, und es gibt automatisch einen für jede Tabelle im System. Barebone Codebeispiel:

CREATE OR REPLACE FUNCTION my_function(_rowtype anyelement) 
    RETURNS SETOF anyelement AS 
$func$ 
BEGIN 
    RETURN QUERY EXECUTE format(
    'SELECT * FROM %s LIMIT 10' 
    , pg_typeof(_rowtype) -- pg_typeof() returns regtype, quoted where necessary 
    ); 
END 
$func$ LANGUAGE plpgsql; 

Call:

SELECT * FROM my_function(NULL::my_table); 

Detaillierte Anleitungen in dieser verwandten Antwort (Blick auf das letzte Kapitel "Verschiedene komplette Tabellentypen"):