PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Postgres pl/pgsql ERRORE:la colonna nome_colonna non esiste

La tua funzione potrebbe assomigliare a questa:

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 o successivo è più semplice con format()

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

%I sfugge a identificatori come quote_ident() .

Punti principali:

  • Stavi incontrando la limitazione dell'SQL dinamico che non puoi usare i parametri per gli identificatori. Devi creare la stringa di query con il nome della colonna e quindi eseguilo.

  • Puoi farlo con i valori però. Dimostro l'uso di USING clausola per EXECUTE . Nota anche l'uso di quote_ident() :impedisce l'iniezione SQL e alcuni errori di sintassi.

  • Ho anche ampiamente semplificato la tua funzione. [RETURN QUERY EXECUTE][3] rende il tuo codice più breve e veloce. Non è necessario eseguire il ciclo se tutto ciò che fai è restituire la riga.

  • Uso denominato IN parametri, in modo da non confondersi con la $-notazione nella stringa di query. $1 e $2 all'interno della stringa di query fare riferimento ai valori forniti in USING clausola, non ai parametri di input.

  • Passo a SELECT * poiché devi comunque restituire l'intera riga in modo che corrisponda al tipo restituito dichiarato.

  • Ultimo ma non meno importante:assicurati di considerare ciò che il manuale ha da dire sulle funzioni dichiarate SECURITY DEFINER .

TIPO DI RESO

Se non vuoi restituire l'intera riga, una comoda possibilità è:

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

Quindi non devi fornire un elenco di definizioni di colonna con ogni chiamata e puoi semplificare in:

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