我有一个如下所示的存储过程,
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;
当我执行这样的查询时:
select * from select_transactions3("invoice_no", '1103300105472',10);
或
select * from select_transactions3(invoice_no, '1103300105472',10);
它得到这样的错误: 错误:“invoice_no”列不存在
但是当我尝试像这样用一个冒号执行时:
select * from select_transactions3('invoice_no', '1103300105472',10);
结果是没有行。
我怎样才能得到这样的数据:
invoice_no | trans_date
---------------+-------------------------
1103300105472 | 2011-03-30 12:25:35.694
谢谢。
更新:如果我们想要显示表格的某一列
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;
得到结果:
SELECT * FROM select_to_transactions14( 'invoice_no', '1103300105472',1)
as ("invoice_no" varchar(125), "amount" numeric(12,2));
最佳答案
您的函数可能如下所示:
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;
在 PostgreSQL 9.1 或更高版本中使用 format()
更简单
...
RETURN QUERY EXECUTE format('
SELECT *
FROM transactions
WHERE %I = $1
LIMIT $2', _col)
USING _val, _limit;
...
%I
转义标识符,例如 quote_ident()
。
要点:
您遇到了不能为标识符使用参数的动态 SQL 的限制。您必须使用列名构建查询字符串,然后执行它。
不过您可以使用值来做到这一点。我演示了
EXECUTE
的USING
子句的使用。还要注意quote_ident()
的使用: 防止 SQL 注入(inject)和某些语法错误。我还大大简化了您的功能。
[RETURN QUERY EXECUTE][3]
使您的代码更短更快。如果您所做的只是返回行,则无需循环。我使用命名的
IN
参数,因此您不会与查询字符串中的 $-notation 混淆。查询字符串中的$1
和$2
是指USING
子句中提供的值,而不是输入参数。我更改为
SELECT *
,因为无论如何您都必须返回整行以匹配声明的返回类型。最后但同样重要的是:一定要考虑手册中关于函数声明的内容
SECURITY DEFINER
.
返回类型
如果您不想返回整行,一种方便的方法是:
CREATE FUNCTION select_transactions3(_col text, _val text, _limit int)
RETURNS TABLE (invoice_no varchar(125), amount numeric(12,2) AS ...
那么您不必在每次调用时都提供列定义列表,并且可以简化为:
SELECT * FROM select_to_transactions3('invoice_no', '1103300105472', 1);
关于postgresql - Postgres pl/pgsql 错误 : column "column_name" does not exist,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9510946/