sql >> Base de Datos >  >> RDS >> PostgreSQL

Postgres pl/pgsql ERROR:la columna column_name no existe

Su función podría verse así:

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;

EN PostgreSQL 9.1 o posterior eso es más simple con format()

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

%I escapa de identificadores como quote_ident() .

Puntos principales:

  • Estaba chocando con la limitación de SQL dinámico que no puede usar parámetros para identificadores. Tienes que construir la cadena de consulta con el nombre de la columna y luego ejecutarlo.

  • Sin embargo, puedes hacer eso con valores. Demuestro el uso del USING cláusula para EXECUTE . También tenga en cuenta el uso de quote_ident() :previene la inyección SQL y ciertos errores de sintaxis.

  • También simplifiqué en gran medida su función. [RETURN QUERY EXECUTE][3] hace que su código sea más corto y más rápido. No es necesario repetir si todo lo que hace es devolver la fila.

  • Uso el nombre IN parámetros, para que no se confunda con la notación $ en la cadena de consulta. $1 y $2 dentro de la cadena de consulta, consulte los valores proporcionados en USING cláusula, no a los parámetros de entrada.

  • Cambio a SELECT * ya que tiene que devolver la fila completa para que coincida con el tipo de devolución declarado de todos modos.

  • Por último, pero no menos importante:asegúrese de considerar lo que dice el manual sobre las funciones declaradas SECURITY DEFINER .

TIPO DE DEVOLUCIÓN

Si no desea devolver la fila completa, una posibilidad conveniente es:

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

Entonces no tiene que proporcionar una lista de definición de columna con cada llamada y puede simplificar a:

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