簡體   English   中英

plpgsql函數:從隨機表創建的視圖中返回行

[英]plpgsql function: Return rows from a view created from random table

我想創建一個函數,該函數返回從未知表創建的視圖中的行:

    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;

在我的情況下,y name是一個變量,我在另一個函數中創建它

它可以像這樣工作:

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;
  • 注意使用對象標識符類型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:錯誤:42601:返回“記錄”的函數需要列定義列表

如果返回類型隨提供的表名稱而變化 ,則仍有更好的解決方案。 由於您使用SELECT * FROM tbl創建視圖,因此可以將表本身的已知類型用作多態參數:

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()進行安全和簡單的字符串連接。

這個相關答案的更多細節:
重構PL / pgSQL函數以返回各種SELECT查詢的輸出

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM