Postgresql

如何將函式返回的記錄插入表中

  • July 13, 2016

我有一個 plpgsql 函式,它接受一個輸入參數並返回多列數據作為記錄。

CREATE FUNCTION my_func(
   IN id bigint,
   OUT foo bigint,
   OUT bar double precision
   )
 RETURNS RECORD AS
$BODY$
BEGIN
   -- some calculations
   foo = id + 1;
   bar = 42.0;
END;
$BODY$
 LANGUAGE plpgsql;

我想以id 列作為輸入參數my_func對錶 ( ) 的每一行執行table_input並將返回的行插入到另一個表 ( table_output) 中。該表table_output具有與返回的列相同的列my_func

我怎樣才能做到這一點?

查詢

SELECT my_func(id) INTO table_output FROM table_input;

給我:

ERROR:  column "my_func" has pseudo-type record

以下查詢執行我想要的操作,但my_func()每行呼叫兩次:

INSERT INTO table_output 
SELECT
(my_func(table_input.id)).foo,
(my_func(table_input.id)).bar
FROM table_input;

有什麼建議?

假設目前 Postgres 版本為 9.5,因為它尚未定義。

最好通過LATERAL連接解決(Postgres 9.3+)。

最小的工作形式:

INSERT INTO table_output
SELECT f.*
FROM   table_input t, my_func(t.id) f;

同樣,更明確:

INSERT INTO table_output (foo, bar)
SELECT f.foo, f.bar
FROM   table_input t
CROSS  JOIN LATERAL my_func(t.id) AS f;

或者,因為在這種情況下只保證了一個結果行,所以子查詢中的普通函式呼叫也是如此,可能更便宜:

INSERT INTO table_output
SELECT f.*
FROM  (SELECT my_func(id) AS f FROM table_input) t;

INSERT即使函式和表的行類型目前匹配,在持久化中聲明目標列也是明智的。這對以後的更改更加穩健。

CROSS JOIN LATERAL只是FROM列表中集合返回函式之前的簡單逗號的詳細等效項。(綁定更緊密,但這與此查詢無關。)

在最近關於 SO 的相關答案中詳細解釋LATERAL以及如何避免重複功能評估- 帶有更多連結:

引用自:https://dba.stackexchange.com/questions/143621