Hata: Bir seti kabul edemeyen bağlamda çağrılan set_valued işlevi. Neyle ilgili?


11

Ben ubuntu 12.04 ile Postgresql 9.1 kullanıyorum.

Sorum için Craig'in cevap esinlenerek SETOF türü veya SETOF kaydın Birleştirme kullandığımı iyi gider diye düşündüm return query, setof recordve bu plpgsql fonksiyonu içine bir dizi jeneratörü:

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;

Yürütme sırasında hatayı alıyorum:

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

Yanlış olan ne ? Craig'in tersine işlevin geri dönmesini söylüyorum setof record.

Tam olarak Craig gibi yapıyor bir şey elde edebilirsiniz, yani bir tür tanımlayarak create type pair_id_value as (idx bigint, value integer)ve benim setof of pair_id_valueyerine plpgsql işlevi bir yerine döner var setof record.

Ama neden bu bile çalışma solüsyonu ile, hala anlamıyorum select id, generate_series(0,13)yalnız bir sonuç dönecektir iki sütun ... ve birlikte fonksiyonu (döndürüyor SETOF pair_id_value) çağıran tersine return query select id, generate_series(0,my_obj.value) from my_objbir sonuç dönecektir tek sütuna hangi alan göz gibi açıkçası tuples olan bu "(123123,0)" "(123123,1)" "(123123,2)" (3 satır).

Geçici bir tablonun oluşturulması / oluşturulması gereken bir durum mu?


Bu, çalıştırdığınız işlevin tam metni olamaz çünkü derlenmez; sonra noktalı virgül BEGINve sonra eksik noktalı virgül var RETURN QUERY. Bu hataları düzelttikten sonra geri dönerken hatayı onaylarım record; cevap olarak açıklayacaktır.
Craig Ringer

@CraigRinger Noktalı virgül yerine koydum.
Stephane Rolland

Yanıtlar:


7

Hata mesajı çok yardımcı değil:

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);

ancak sorguyu uygun bir küme döndürme işlevi olarak adlandırmak üzere yeniden ifade ederseniz asıl sorunu görürsünüz:

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);

Eğer kullanıyorsanız SETOF RECORDbir olmadan OUTparametre listesinden aradığınız açıklamada, mesela sonuçları belirtmelidir:

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

Ancak, parametreleri RETURNS TABLEveya OUTparametreleri kullanmak çok daha iyidir . Önceki sözdizimi ile işleviniz şöyle olacaktır:

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;

Bu, SELECT listesi bağlamında çağrılabilir ve açıkça bir tür oluşturmadan veya çağrı sitesinde sonuç yapısını belirtmeden kullanılabilir.


Sorunun ikinci yarısına gelince, olan şey 1. durumun bir SELECT listesinde iki ayrı sütun belirtmesidir, ikincisi tek bir bileşik döndürür. Aslında sonucu nasıl döndürdüğünüzle değil, işlevi nasıl çağırdığınızla ilgilidir. Örnek işlevi yaratırsak:

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

Bir set döndüren işlevi çağırmanın iki yolundaki farkı göreceksiniz - SELECTlistede, ilginç bir davranışa sahip PostgreSQL'e özgü standart dışı bir uzantı:

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

veya daha standart bir şekilde bir tablo olarak:

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

Sadece test edildi, mükemmel çalışıyor. Ve bu sözdizimini seviyorum returns table.
Stephane Rolland

@StephaneRolland Sorunun ikinci kısmının da açıklamasıyla güncellendi.
Craig Ringer

destek için teşekkürler. Şimdi çok daha net.
Stephane Rolland
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.