Używam Postgresql 9.1, z Ubuntu 12.04.
Zainspirowany odpowiedź Craiga do mojego zapytania połączeniem setof typu lub setof rekordu myślałem, że go dobrze z użyciem return query
, setof record
oraz generator serii do tej funkcji 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;
Podczas wykonywania pojawia się błąd:
ERROR: set_valued function called in context that cannot accept a set
Co jest nie tak ? W przeciwieństwie do Craiga mówię funkcji, aby powróciła setof record
.
Mogę osiągnąć coś, co działa dokładnie tak, jak Craig, tj. Definiując typ create type pair_id_value as (idx bigint, value integer)
i zwracając funkcję plpgsql setof of pair_id_value
zamiast a setof record
.
Ale nawet z tym działającym rozwiązaniem nadal nie rozumiem, dlaczego select id, generate_series(0,13)
sam zwróci wynik w dwóch kolumnach ... a wręcz przeciwnie, wywołanie funkcji (zwraca setof para_id_value) z return query select id, generate_series(0,my_obj.value) from my_obj
zwróci wynik tylko w jednej kolumnie, której pole wygląda jak ten „(123123,0)” „(123123,1)” „(123123,2)” (3 rzędy), które są oczywiście krotkami.
Czy jest to przypadek, w którym należy / należy utworzyć tymczasową tabelę?
źródło
BEGIN
i brakujący poRETURN QUERY
. Po poprawieniu tych błędów potwierdzam błąd przy powrocierecord
; wyjaśni w odpowiedzi.Odpowiedzi:
Komunikat o błędzie nie jest zbyt pomocny:
ale jeśli przepiszesz zapytanie w celu wywołania go jako właściwej funkcji zwracającej zestaw, zobaczysz prawdziwy problem:
Jeśli używasz
SETOF RECORD
bezOUT
listy parametrów, musisz określić wyniki w instrukcji wywołania, np .:Jednak znacznie lepiej jest użyć
RETURNS TABLE
lubOUT
parametrów. Przy poprzedniej składni twoją funkcją byłoby:Jest to możliwe do wywołania w kontekście listy SELECT i może być używane bez jawnego tworzenia typu lub określania struktury wyników w witrynie wywołującej.
Jeśli chodzi o drugą połowę pytania, dzieje się tak, że pierwszy przypadek określa dwie oddzielne kolumny na liście WYBIERZ, a druga zwraca pojedynczy kompozyt. W rzeczywistości nie ma to związku z tym, jak zwracasz wynik, ale z tym, jak wywołujesz funkcję. Jeśli utworzymy przykładową funkcję:
Zobaczysz różnicę na dwa sposoby wywoływania funkcji zwracającej zestaw - na
SELECT
liście niestandardowe rozszerzenie PostgreSQL o dziwnym działaniu:lub jako tabela w bardziej standardowy sposób:
źródło
returns table
.