我需要创建一个函数,该函数将运行查询并返回结果,其中包含表名和列名,这些名称是赋予函数的arugments。我目前有这个:
CREATE OR REPLACE FUNCTION qa_scf(tname character varying, cname character varying)
RETURNS SETOF INT AS
$BODY$
BEGIN
RETURN QUERY SELECT * FROM tname WHERE cname !='AK' AND cname!='CK';
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100
ROWS 1000;
这给了我运行时错误“关系'tname'不存在”。我是Postgres的新功能,所以任何帮助都表示赞赏。我觉得返回int是错误的,但我不知道还有什么可以让它返回返回行的所有列。谢谢!
答案 0 :(得分:18)
您无法使用变量代替此类标识符。您需要使用动态查询。它看起来像这样:
EXECUTE 'SELECT * FROM ' || quote_ident(tname)
|| ' WHERE ' || quote_ident(cname) || ' NOT IN (''AK'',''CK'');'
INTO result_var;
如果您使用的是PostgreSQL 9.1或更高版本,则可以使用the format() function,这样可以更轻松地构建此字符串。
答案 1 :(得分:14)
如果不动态构造要作为动态语句执行的字符串,则不能将表和列名指定为参数或变量。 Postgres有关于executing dynamic statements的优秀介绍性文档。使用quote_ident()
或quote_literal()
正确引用标识符和文字非常重要。 format()函数有助于清理动态sql语句构造。由于您声明函数返回SETOF INTEGER
,因此您应该选择所需的整数字段,而不是*
。
CREATE OR REPLACE FUNCTION qa_scf(tname text, cname text)
RETURNS SETOF INTEGER AS
$BODY$
BEGIN
RETURN QUERY EXECUTE format(
'SELECT the_integer_field FROM %I WHERE %I NOT IN (%L, %L)',
tname, cname, 'AK', 'CK'
);
END;
$BODY$
LANGUAGE plpgsql;