PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Postgres pl/pgsql ERRO:coluna column_name não existe


Sua função pode ficar assim:
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;

NO PostgreSQL 9.1 ou posterior, é mais simples com o formato format()
...
RETURN QUERY EXECUTE format('
   SELECT *
   FROM   transactions
   WHERE  %I = $1
   LIMIT  $2', _col)
USING _val, _limit;
...

%I escapa de identificadores como quote_ident() .

Pontos principais:


  • Você estava se deparando com a limitação do SQL dinâmico que não pode usar parâmetros para identificadores. Você tem que construir a string de consulta com o nome da coluna e depois execute.

  • Você pode fazer isso com valores embora. Demonstro o uso do USING cláusula para EXECUTE . Observe também o uso de quote_ident() :evita a injeção de SQL e certos erros de sintaxe.

  • Eu também simplifiquei amplamente sua função. [RETURN QUERY EXECUTE][3] torna seu código mais curto e mais rápido. Não há necessidade de fazer um loop se tudo o que você faz é retornar a linha.

  • Eu uso nomeado IN parâmetros, para que você não fique confuso com a notação $ na string de consulta. $1 e $2 dentro da string de consulta referem-se aos valores fornecidos no USING cláusula, não aos parâmetros de entrada.

  • Eu mudo para SELECT * pois você precisa retornar a linha inteira para corresponder ao tipo de retorno declarado de qualquer maneira.

  • Por último, mas não menos importante:Certifique-se de considerar o que o manual tem a dizer sobre as funções declaradas SECURITY DEFINER .

TIPO DE DEVOLUÇÃO


Se você não quiser retornar a linha inteira, uma possibilidade conveniente é:
CREATE FUNCTION select_transactions3(_col text, _val text, _limit int)    
  RETURNS TABLE (invoice_no varchar(125), amount numeric(12,2) AS ...

Então você não precisa fornecer uma lista de definição de coluna com cada chamada e pode simplificar para:
SELECT * FROM select_to_transactions3('invoice_no', '1103300105472', 1);