USING deyimi ile JOIN sonucu işlev parametresi ve adlandırma çakışması


17

Mevcut Postgres 9.4'te ( bu ilgili sorudan ) bu kurulum göz önüne alındığında :

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

Önceki sorudan bir SQL Fiddle da var .

A SELECTile FULL JOINyazılan sorunun amacına ulaşmak için bir ile yazdım . Basitleştirilmiş:

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

Spesifikasyonlara göre, sütuna hitap etmenin doğru yolu tstablo niteliksizdir. Giriş değerlerinden ( f.tsveya b.ts) her ikisi de NULL olabilir. USINGFıkra garip bir durum biraz oluşturur: aslında giriş mevcut değil bir "giriş" sütunu tanıtan. Şimdiye kadar çok zarif.

Bunu bir plpgsql işlevine koydum. Kolaylık (veya gereksinimler) için tablo işlevinin sonucu için aynı sütun adlarını istiyorum. Bu nedenle, aynı sütun adları ile işlev parametreleri arasındaki adlandırma çakışmalarını önlemek zorundayız. Farklı isimler seçerek kaçınılmalıdır, ama işte buradayız:

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;

Sorunu vurgulamak için cesur vurgu . Daha tsönce olduğu gibi tablo yeterlilik olmadan kullanamam , çünkü plpgsql bir istisna (kesinlikle gerekli değildir, ancak muhtemelen çoğu durumda yararlıdır) yükseltir:

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.

Farklı isimler veya alt sorgular ya da başka bir fonksiyon kullanabileceğimi biliyorum. Ancak, sütuna başvurmanın bir yolu olup olmadığını merak ediyorum. Tablo kalifikasyonunu kullanamıyorum. Kişi bir yol olması gerektiğini düşünürdü .
Var mı?

Yanıtlar:


19

PL / pgSQL belgelerine göre Kaput altında,plpgsql.variable_conflict işlevi oluşturmadan önce veya işlev tanımının başlangıcında, bu tür çakışmaların nasıl çözülmesini istediğinizi bildiren yapılandırma parametresini kullanabilirsiniz error(varsayılan 3 değer ( ) use_variableve 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
Mükemmel. Ben bir şey eksik olduğum nagging hissi vardı. Aslında bunu geçmişte kullandığımı hatırlıyorum. Teşekkür ederim!
Erwin Brandstetter
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.