Postgresql

錯誤:在不能接受集合的上下文中呼叫 set_valued 函式。它是關於什麼的?

  • February 28, 2018

我使用 Postgresql 9.1 和 ubuntu 12.04。

受 Craig 對我的問題Concatenation of setof type or setof record的啟發,我想我可以很好地使用return query,setof record和一個系列生成器到這個 plpgsql 函式中:

create or replace function compute_all_pair_by_craig(id_obj bigint)
   returns setof record as $$
begin
   return query select o.id, generate_series(0,o.value) from m_obj as o;     
end;
$$    language plpgsql;

在執行期間,我收到錯誤:

ERROR: set_valued function called in context that cannot accept a set

怎麼了 ?與克雷格相反,我告訴函式 return setof record

我可以實現與 Craig 完全一樣的工作,即通過定義一個類型create type pair_id_value as (idx bigint, value integer)並讓我的 plpgsql 函式返回 asetof of pair_id_value而不是 a setof record

但是即使使用這個可行的解決方案,我仍然不明白為什麼select id, generate_series(0,13)單獨會在兩列中返回結果……相反,呼叫函式(返回 setof pair_id_value)只會在欄位看起來像的一列return query select id, generate_series(0,my_obj.value) from my_obj中返回結果這個“(123123,0)”“(123123,1)”“(123123,2)”(3行)顯然是元組。

是否必須/應該創建臨時表?

錯誤消息不是很有幫助:

regress=> SELECT * FROM  compute_all_pair_by_craig(100);
ERROR:  a column definition list is required for functions returning "record"
LINE 1: SELECT * FROM  compute_all_pair_by_craig(100);

但是,如果您改寫查詢以將其稱為正確的集合返回函式,您將看到真正的問題:

regress=> SELECT * FROM compute_all_pair_by_craig(100);
ERROR:  a column definition list is required for functions returning "record"
LINE 1: SELECT * FROM compute_all_pair_by_craig(100);

如果您在SETOF RECORD沒有OUT參數列表的情況下使用,則必須在呼叫語句中指定結果,例如:

regress=> SELECT * FROM compute_all_pair_by_craig(100) theresult(a integer, b integer);

RETURNS TABLE但是,使用或OUT參數要好得多。使用前一種語法,您的函式將是:

create or replace function compute_all_pair_by_craig(id_obj bigint)
   returns table(a integer, b integer) as $$
begin
   return query select o.id, generate_series(0,o.value) from m_obj as o;     
end;
$$ language plpgsql;

這在 SELECT-list 上下文中是可呼叫的,並且可以在不顯式創建類型或在呼叫站點指定結果結構的情況下使用。


至於問題的後半部分,發生的情況是第一種情況在 SELECT 列表中指定了兩個單獨的列,而第二種情況返回單個組合。這實際上與您如何返回結果無關,而是您如何呼叫該函式。如果我們創建範例函式:

CREATE OR REPLACE FUNCTION twocols() RETURNS TABLE(a integer, b integer) 
AS $$ SELECT x, x FROM generate_series(1,5) x; $$ LANGUAGE sql;

您將看到呼叫 set-returning 函式的兩種方式的區別 - 在SELECT列表中,一個具有古怪行為的 PostgreSQL 特定非標準擴展:

regress=> SELECT twocols();
twocols 
---------
(1,1)
(2,2)
(3,3)
(4,4)
(5,5)
(5 rows)

或以更標準的方式作為表格:

regress=> SELECT * FROM twocols();
a | b 
---+---
1 | 1
2 | 2
3 | 3
4 | 4
5 | 5
(5 rows)

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