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

Postgres pl/pgsql FEHLER:Spalte Spaltenname existiert nicht

Ihre Funktion könnte so aussehen:

CREATE FUNCTION select_transactions3(_col text, _val text, _limit int)    
  RETURNS SETOF transactions AS   
$BODY$   
BEGIN

RETURN QUERY EXECUTE '
   SELECT *
   FROM   transactions
   WHERE  ' || quote_ident(_col) || ' = $1
   LIMIT  $2'
USING _val, _limit;

END;   
$BODY$  
LANGUAGE plpgsql VOLATILE SECURITY DEFINER;

IN PostgreSQL 9.1 oder später ist das einfacher mit dem Format format()

...
RETURN QUERY EXECUTE format('
   SELECT *
   FROM   transactions
   WHERE  %I = $1
   LIMIT  $2', _col)
USING _val, _limit;
...

%I maskiert Identifikatoren wie quote_ident() .

Hauptpunkte:

  • Sie sind auf die Einschränkung von dynamischem SQL gestoßen, dass Sie keine Parameter für Bezeichner verwenden können. Sie müssen den Abfragestring mit dem Spaltennamen und dann aufbauen ausführen.

  • Sie können dies jedoch mit Werten tun. Ich demonstriere die Verwendung von USING Klausel für EXECUTE . Beachten Sie auch die Verwendung von quote_ident() :verhindert SQL-Injection und bestimmte Syntaxfehler.

  • Ich habe auch Ihre Funktion stark vereinfacht. [RETURN QUERY EXECUTE][3] macht Ihren Code kürzer und schneller. Es ist keine Schleife erforderlich, wenn Sie nur die Zeile zurückgeben.

  • Ich verwende den Namen IN Parameter, damit Sie nicht mit der $-Notation in der Abfragezeichenfolge verwechselt werden. $1 und $2 innerhalb der Abfragezeichenfolge beziehen sich auf die in USING bereitgestellten Werte -Klausel, nicht zu den Eingabeparametern.

  • Ich wechsle zu SELECT * da Sie sowieso die gesamte Zeile zurückgeben müssen, um mit dem deklarierten Rückgabetyp übereinzustimmen.

  • Last but not least:Achten Sie darauf, was das Handbuch zu Funktionen zu sagen hat, die als SECURITY DEFINER .

RÜCKGABEART

Wenn Sie nicht die ganze Zeile zurückgeben möchten, gibt es eine bequeme Möglichkeit:

CREATE FUNCTION select_transactions3(_col text, _val text, _limit int)    
  RETURNS TABLE (invoice_no varchar(125), amount numeric(12,2) AS ...

Dann müssen Sie nicht bei jedem Aufruf eine Spaltendefinitionsliste angeben und können vereinfachen zu:

SELECT * FROM select_to_transactions3('invoice_no', '1103300105472', 1);