ข้อผิดพลาด: ฟังก์ชัน set_valued เรียกในบริบทที่ไม่สามารถยอมรับชุดได้ มันเกี่ยวกับอะไร?


11

ฉันใช้ Postgresql 9.1 กับ Ubuntu 12.04

ได้รับแรงบันดาลใจจากคำตอบของ Craig ต่อคำถามของฉันการเรียง setof หรือ 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

เกิดอะไรขึ้น ? setof recordขัดกับเครกผมบอกฟังก์ชั่นการกลับมา

ฉันสามารถบรรลุสิ่งที่ทำงานทำเหมือนเครกคือโดยการกำหนดประเภทcreate type pair_id_value as (idx bigint, value integer)และมีฟังก์ชั่น plpgsql ผลตอบแทนของฉันแทนsetof of pair_id_valuesetof 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 แถว) ซึ่งเห็นได้ชัดว่าเป็นสิ่งอันดับ

เป็นกรณีที่ต้องสร้าง / สร้างตารางชั่วคราวหรือไม่?


นั่นไม่สามารถเป็นข้อความที่แน่นอนของฟังก์ชั่นที่คุณใช้เพราะไม่ได้รวบรวม มีเซมิโคลอนส่วนเกินBEGINและขาดหายไปหลังจากRETURN QUERYนั้น หลังจากแก้ไขข้อผิดพลาดฉันยืนยันข้อผิดพลาดเมื่อกลับมาrecord; จะอธิบายในคำตอบ
Craig Ringer

@ CraigRinger ฉันใส่อัฒภาคกลับมาอยู่ที่เดิม
Stephane Rolland

คำตอบ:


7

ข้อความแสดงข้อผิดพลาดไม่เป็นประโยชน์มาก:

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;

นี่คือ callable ในบริบทรายการเลือกและสามารถนำมาใช้โดยไม่ต้องสร้างประเภทอย่างชัดเจนหรือระบุโครงสร้างผลลัพธ์ที่ไซต์การโทร


สำหรับครึ่งหลังของคำถามสิ่งที่เกิดขึ้นคือกรณีที่ 1 ระบุคอลัมน์สองคอลัมน์แยกกันในรายการที่เลือกโดยที่สองจะส่งคืนคอมโพสิตเดียว ที่จริงแล้วมันไม่ได้เกี่ยวกับวิธีที่คุณส่งคืนผลลัพธ์ แต่วิธีที่คุณเรียกใช้ฟังก์ชัน ถ้าเราสร้างฟังก์ชั่นตัวอย่าง:

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

คุณจะเห็นความแตกต่างในสองวิธีในการเรียกใช้ฟังก์ชั่น set-return - ใน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)

แค่ทดสอบใช้งานได้สมบูรณ์ returns tableและผมชอบรูปแบบนี้ด้วย
Stephane Rolland

@StephaneRolland อัปเดตพร้อมคำอธิบายส่วนหลังของคำถามด้วย
Craig Ringer

ขอบคุณสำหรับการสนับสนุน ตอนนี้มันชัดเจนกว่ามาก
Stephane Rolland
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.