Postgresql
如何將函式返回的記錄插入表中
我有一個 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
以及如何避免重複功能評估- 帶有更多連結: