Конфликт имен между параметром функции и результатом JOIN с предложением USING

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

Существует также SQL Fiddle из предыдущего вопроса.

Я написал SELECTс, FULL JOINчтобы достичь цели упомянутого вопроса. Упрощенная:

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

Согласно спецификациям, правильный способ обращения к столбцу tsбез указания таблицы. Любое из входных значений ( f.tsили b.ts) может быть NULL. Предложение USINGсоздает немного странный случай: ввод столбца «input», который на самом деле отсутствует во входных данных. Пока все так элегантно.

Я положил это в функцию 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;
ypercubeᵀᴹ
источник
1
Отлично. У меня было ноющее ощущение, что я что-то упустил. Я действительно помню, что использовал это в прошлом. Спасибо!
Эрвин Брандштеттер