Penamaan konflik antara parameter fungsi dan hasil GABUNG dengan MENGGUNAKAN klausa

16

Dengan pengaturan ini pada Postgres 9.4 saat ini ( dari pertanyaan terkait ini ):

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

Ada juga SQL Fiddle dari pertanyaan sebelumnya.

Saya menulis SELECTdengan a FULL JOINuntuk mencapai tujuan dari pertanyaan yang dirujuk. Sederhana:

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

Sesuai spesifikasi, cara yang benar untuk mengatasi kolom tsadalah tanpa kualifikasi tabel. Salah satu dari nilai input ( f.tsatau b.ts) dapat NULL. The USINGklausul menciptakan sedikit kasus aneh: memperkenalkan "masukan" kolom yang tidak benar-benar hadir dalam input. Sejauh ini elegan.

Saya menempatkan ini dalam fungsi plpgsql. Untuk kenyamanan (atau persyaratan) saya ingin nama kolom yang sama untuk hasil dari fungsi tabel. Jadi kita harus menghindari konflik penamaan antara nama kolom yang identik dan parameter fungsi. Sebaiknya dihindari dengan memilih nama yang berbeda, tetapi di sini kita:

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;

Penekanan berani untuk menyoroti masalah . Saya tidak dapat menggunakan tstanpa kualifikasi tabel seperti sebelumnya, karena plpgsql akan memunculkan pengecualian (tidak sepenuhnya diperlukan, tetapi mungkin berguna dalam kebanyakan kasus):

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.

Saya tahu saya bisa menggunakan nama atau subquery yang berbeda atau menggunakan fungsi lain. Tapi saya ingin tahu apakah ada cara untuk referensi kolom. Saya tidak bisa menggunakan kualifikasi tabel. Orang akan berpikir harus ada jalan.
Disana?

Erwin Brandstetter
sumber

Jawaban:

18

Menurut dokumen PL / pgSQL Di Balik Terpal , Anda dapat menggunakan parameter konfigurasi plpgsql.variable_conflict, baik sebelum membuat fungsi atau di awal definisi fungsi, menyatakan bagaimana Anda ingin konflik tersebut diselesaikan (3 nilai yang mungkin adalah error(default) ), use_variabledan 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;
ypercubeᵀᴹ
sumber
1
Sempurna. Aku punya sensasi mengomel bahwa aku kehilangan sesuatu. Saya benar-benar ingat pernah menggunakannya di masa lalu. Terima kasih!
Erwin Brandstetter