plpgsql函数:从随机表创建的视图中返回行

时间:2014-02-14 11:36:23

标签: postgresql record plpgsql

我想创建一个函数,该函数返回从未知表创建的视图中的行:

    CREATE OR REPLACE FUNCTION tt_query(text, timestamp without time zone)
      RETURNS SETOF record AS
    $$
    DECLARE

    orig_name ALIAS FOR $1;
    data_tt ALIAS FOR $2;

    BEGIN

    [...]

    EXECUTE 'create OR REPLACE TEMP view temp as 
    select * 
    from  '
    ||orig_name 
    ||' where trigger_changed >'
    ||quote_literal(data_tt)
    ||' ORDER BY trigger_changed DESC';

    [...]--other work on view temp

    --NOW I WANT RETURN THE ROW OF view temp
    END;
    $$
    LANGUAGE plpgsql VOLATILE

好的我想(有你的帮助)这个:

表:

create table t(a integer, b text);

功能:

CREATE OR REPLACE FUNCTION f()
  RETURNS SETOF record AS
$$
BEGIN

RETURN QUERY EXECUTE 'SELECT * FROM t';

END;
  $$
  LANGUAGE plpgsql VOLATILE

型:

CREATE TYPE y AS (
    a int,
    b text
);

现在可以吗?:

select * from f() as y;
在我的案例中,

是一个变量,我在另一个函数中创建它

1 个答案:

答案 0 :(得分:3)

它可以像这样工作:

CREATE OR REPLACE FUNCTION tt_query(orig_name regclass, data_tt timestamp)
  RETURNS SETOF record AS
$func$
BEGIN

EXECUTE 'CREATE OR REPLACE TEMP VIEW tmp as 
select * 
from  '
|| orig_name 
|| ' where trigger_changed >'
|| quote_literal(data_tt)
|| ' ORDER BY trigger_changed DESC';

-- other work on view tmp

-- return the rows of view temp
RETURN QUERY
SELECT * FROM tmp;

END
$func$  LANGUAGE plpgsql;
  • 请注意使用object identifier type regclass自动避免SQL注入。

  • 如果您不需要,请不要使用过时的语法var ALIAS for $1。改为声明参数名称。

  • 我不会使用关键字temp作为标识符,即使这是允许的。改为使用tmp

  • 使用RETURN QUERY返回一组记录。这甚至可以是没有EXECUTE的静态呼叫。但是,每次通话都会返回匿名记录,Postgres要求列定义列表

SELECT * FROM tt_query('tbl_name', '2014-02-15 12:00')
AS f(col1 int, col2 text, ...);

这是相当笨拙的。

更好的解决方案

如果您知道返回类型(即使表名称正在更改,列列表可能共享相同的类型),请在创建时声明它。考虑这个相关的问题:
PostgreSQL: ERROR: 42601: a column definition list is required for functions returning "record"

如果返回类型与所提供的表名称不同,则仍有更好的解决方案。由于您使用SELECT * FROM tbl创建了一个视图,因此您可以将表格的众所周知类型用作polymorphic参数:

CREATE OR REPLACE FUNCTION tt_query(orig_name anyelement, data_tt timestamp)
  RETURNS SETOF anyelement AS
$func$
BEGIN

EXECUTE format('CREATE OR REPLACE TEMP VIEW tmp AS
   SELECT * FROM  %s
   WHERE  trigger_changed > %L
   ORDER  BY trigger_changed DESC'
  ,pg_typeof(orig_name)
  ,data_tt);

-- other work on view tmp

-- return the rows of view tmp
RETURN QUERY
SELECT * FROM tmp;

END
$func$  LANGUAGE plpgsql;

简化电话:

SELECT * FROM tt_query(NULL::tbl_name, '2014-02-15 12:00');

同时使用format()安全&简单的字符串连接。

此相关答案的更多细节:
Refactor a PL/pgSQL function to return the output of various SELECT queries