関数パラメーターとUSING句を使用したJOINの結果との名前の競合


16

現在の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句は、奇妙なケースを少し作成します。実際には入力に存在しない「入力」列を導入します。これまでのところとてもエレガント。

これを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;

問題を強調するための大胆な強調。tsplpgsqlは例外を発生させるため(厳密には必要ではありませんが、ほとんどの場合に役立つ可能性があります)、以前のようにテーブル修飾なしで使用することはできません。

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.

別の名前やサブクエリを使用したり、別の関数を使用したりできることを知っています。しかし、列を参照する方法があるのだろうか。テーブル修飾を使用できません。方法があるはずだと思うでしょう。
ある?

回答:


18

PL / pgSQL Under the Hoodによると、構成パラメーターを使用してplpgsql.variable_conflict、関数を作成する前または関数定義の開始時に、このような競合を解決する方法を宣言できますerror(3つの可能な値は(デフォルト)、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
パーフェクト。何かが足りないというしつこい感覚がありました。過去にそれを使ったことを覚えています。ありがとうございました!
アーウィンブランドステッター
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.