15

我需要创建一个函数来运行查询并返回结果,表名和列名是给函数的参数。我目前有这个:

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'des不存在”。我是为 Postgres 创建函数的新手,因此不胜感激。我觉得 return int 是错误的,但我不知道还有什么可以让它返回返回行的所有列。谢谢!

4

2 回答 2

24

您不能使用变量代替这样的标识符。您需要使用动态查询来完成。它看起来像这样:

EXECUTE 'SELECT * FROM ' || quote_ident(tname) 
        || ' WHERE ' || quote_ident(cname) || ' NOT IN (''AK'',''CK'');'
INTO result_var;

如果您使用的是 PostgreSQL 9.1 或更高版本,则可以使用format() 函数,它可以更轻松地构建此字符串。

于 2012-05-17T17:23:59.737 回答
17

如果不动态构造字符串以作为动态语句执行,则无法将表名和列名指定为参数或变量。Postgres 有关于执行动态语句的优秀介绍文档。quote_ident()用or正确引用标识符和文字很重要quote_literal()format()函数有助于清理动态 sql 语句构造。由于您将函数声明为 return 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;
于 2012-05-17T17:50:58.900 回答