Postgres pl/pgsql ERROR: column “column_name” does not exist

家住魔仙堡 提交于 2019-12-19 04:22:07

问题


i have a storerd procedure like below,

CREATE FUNCTION select_transactions3(text, text, int)    
RETURNS SETOF transactions AS   
$body$   
DECLARE    
    rec transactions%ROWTYPE;  
BEGIN
    FOR rec IN (SELECT invoice_no, trans_date FROM transactions WHERE $1 = $2 limit $3  )    
    LOOP     
        RETURN NEXT rec;    
    END LOOP;  
END;   
$body$  
LANGUAGE plpgsql VOLATILE SECURITY DEFINER;

when i execute query like this :

select * from select_transactions3("invoice_no", '1103300105472',10);

or

select * from select_transactions3(invoice_no, '1103300105472',10);

it getting error like this : ERROR: column "invoice_no" does not exist

but when i try execute with one colon like this :

select * from select_transactions3('invoice_no', '1103300105472',10);

the result is no row.

how i can get the data like this :

  invoice_no   |       trans_date        
---------------+-------------------------
 1103300105472 | 2011-03-30 12:25:35.694

thanks .

UPDATE : If we want a certain column of table that we want to show

CREATE FUNCTION select_to_transactions14(_col character varying, _val character varying, _limit int) 
RETURNS SETOF RECORD AS
$$
DECLARE
 rec record;
BEGIN
 FOR rec IN EXECUTE 'SELECT invoice_no, amount FROM transactions
                 WHERE  ' || _col || ' = $1 LIMIT $2' USING _val, _limit            LOOP
  RETURN NEXT rec;
 END LOOP;
END;
$$ LANGUAGE plpgsql;

to get the result :

SELECT * FROM select_to_transactions14( 'invoice_no', '1103300105472',1)
as ("invoice_no" varchar(125), "amount" numeric(12,2));

回答1:


Your function could look like this:

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 or later that's simpler with format()

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

%I escapes identifiers like quote_ident().

Major points:

  • You were bumping into the limitation of dynamic SQL that you cannot use parameters for identifiers. You have to build the query string with the column name and then execute it.

  • You can do that with values though. I demonstrate the use of the USING clause for EXECUTE. Also note the use of quote_ident(): prevents SQL injection and certain syntax errors.

  • I also largely simplified your function. [RETURN QUERY EXECUTE][3] makes your code shorter and faster. No need to loop if all you do is return the row.

  • I use named IN parameters, so you don't get confused with the $-notation in the query string. $1 and $2 inside the query string refer to the values provided in the USING clause, not to the input parameters.

  • I change to SELECT * as you have to return the whole row to match the declared return type anyway.

  • Last but not least: Be sure to consider what the manual has to say about functions declared SECURITY DEFINER.

RETURN TYPE

If you don't want to return the whole row, one convenient possibility is:

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

Then you don't have to provide a column definition list with every call and can simplify to:

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


来源:https://stackoverflow.com/questions/9510946/postgres-pl-pgsql-error-column-column-name-does-not-exist

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!