การตั้งชื่อความขัดแย้งระหว่างฟังก์ชั่นพารามิเตอร์และผลลัพธ์ของการเข้าร่วมกับการใช้ข้อ


17

รับการตั้งค่านี้ใน Postgres ปัจจุบัน 9.4 ( จากคำถามที่เกี่ยวข้อง ):

CREATE TABLE foo (ts, foo) AS 
VALUES (1, 'A')  -- int, text
     , (7, 'B');

CREATE TABLE bar (ts, bar) AS
VALUES (3, 'C')
     , (5, 'D')
     , (9, 'E');

นอกจากนี้ยังมีซอ Fiddleจากคำถามก่อนหน้านี้

ฉันเขียนSELECTด้วยFULL JOINเพื่อให้บรรลุวัตถุประสงค์ของคำถามอ้างอิง ย่อ:

SELECT ts, f.foo, b.bar
FROM   foo f
FULL   JOIN bar b USING (ts);

ตามข้อมูลจำเพาะวิธีที่ถูกต้องในการจัดการคอลัมน์tsคือไม่มีการรับรองตาราง อย่างใดอย่างหนึ่งของการป้อนข้อมูลค่า ( f.tsหรือb.ts) อาจเป็นโมฆะ USINGประโยคสร้างบิตของกรณีแปลก: แนะนำ "ป้อนข้อมูล" คอลัมน์ที่ไม่จริงในปัจจุบันในการป้อนข้อมูล จนถึงตอนนี้สง่างาม

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

CREATE OR REPLACE FUNCTION f_merge_foobar()
  RETURNS TABLE(ts int, foo text, bar text) AS
$func$
BEGIN
   FOR ts, foo, bar IN
      SELECT COALESCE(f.ts, b.ts), f.foo, b.bar
      FROM   foo f
      FULL   JOIN bar b USING (ts)
   LOOP
      -- so something
      RETURN NEXT;
   END LOOP;
END
$func$ LANGUAGE plpgsql;

เน้นตัวหนาเพื่อเน้นปัญหา ฉันไม่สามารถใช้tsหากไม่มีการรับรองตารางเหมือนก่อนเพราะ plpgsql จะเพิ่มข้อยกเว้น (ไม่จำเป็นอย่างเคร่งครัด แต่อาจมีประโยชน์ในกรณีส่วนใหญ่):

ERROR:  column reference "ts" is ambiguous
LINE 1: SELECT ts, f.foo, b.bar
               ^
DETAIL:  It could refer to either a PL/pgSQL variable or a table column.

ฉันรู้ว่าฉันสามารถใช้ชื่ออื่นหรือแบบสอบถามย่อยหรือใช้ฟังก์ชั่นอื่น แต่ฉันสงสัยว่ามีวิธีอ้างอิงคอลัมน์หรือไม่ ฉันไม่สามารถใช้การรับรองตาราง ใครจะคิดว่าควรมีวิธี
มีอะไรบ้าง

คำตอบ:


19

ตามเอกสารPL / pgSQL ภายใต้ฮูดคุณสามารถใช้พารามิเตอร์การกำหนดค่าplpgsql.variable_conflictก่อนที่จะสร้างฟังก์ชั่นหรือในช่วงเริ่มต้นของการกำหนดฟังก์ชั่นประกาศว่าคุณต้องการแก้ไขข้อขัดแย้งดังกล่าว (ค่าที่เป็นไปได้ 3 ค่าคือerrorค่าเริ่มต้น ) use_variableและuse_column):

CREATE OR REPLACE FUNCTION pg_temp.f_merge_foobar()
  RETURNS TABLE(ts int, foo text, bar text) AS
$func$
#variable_conflict use_column             -- how to resolve conflicts
BEGIN
   FOR ts, foo, bar IN
      SELECT ts, f.foo, b.bar
      FROM   foo f
      FULL   JOIN bar b USING (ts)
   LOOP
      -- do something
      RETURN NEXT;
   END LOOP;
END
$func$ LANGUAGE plpgsql;

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