Conflitto di denominazione tra parametro della funzione e risultato di JOIN con la clausola USING


17

Data questa configurazione nell'attuale Postgres 9.4 ( da questa domanda correlata ):

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

C'è anche un violino SQL dalla domanda precedente.

Ho scritto a SELECTcon a FULL JOINper raggiungere l'obiettivo della domanda di riferimento. semplificata:

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

Secondo le specifiche, il modo corretto di indirizzare la colonna tsè senza qualificazione della tabella. Uno dei valori di input ( f.tso b.ts) può essere NULL. La USINGclausola crea un po 'di un caso strano: l'introduzione di una colonna "input" che non è effettivamente presente nell'input. Fin qui tutto così elegante.

L'ho messo in una funzione plpgsql. Per comodità (o requisiti) voglio gli stessi nomi di colonna per il risultato della funzione tabella. Quindi dobbiamo evitare conflitti di denominazione tra nomi di colonna identici e parametri di funzione. Dovrebbe essere evitato meglio selezionando nomi diversi, ma eccoci qui:

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;

Enorme enfasi per evidenziare il problema . Non posso usare tssenza la qualificazione della tabella come prima, perché plpgsql solleverebbe un'eccezione (non strettamente necessario, ma probabilmente utile nella maggior parte dei casi):

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.

So che posso usare nomi diversi o una sottoquery o usare un'altra funzione. Ma mi chiedo se c'è un modo per fare riferimento alla colonna. Non riesco a usare la qualifica per tavolo. Si potrebbe pensare che ci dovrebbe essere un modo.
È lì?

Risposte:


19

Secondo i documenti PL / pgSQL Under the Hood , è possibile utilizzare il parametro di configurazione plpgsql.variable_conflict, prima di creare la funzione o all'inizio della definizione della funzione, dichiarando come si desidera risolvere tali conflitti (i 3 valori possibili sono error(impostazione predefinita ) use_variablee 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
Perfetto. Ho avuto la fastidiosa sensazione che mi mancasse qualcosa. Ricordo di averlo usato in passato. Grazie!
Erwin Brandstetter,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.