使用USING子句命名函数参数和JOIN结果之间的冲突


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.tsb.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;

强调强调问题。我不能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.

我知道我可以使用其他名称或子查询,也可以使用其他功能。但是我想知道是否有一种方法可以引用该专栏。我不能使用表资格。有人会认为应该有办法。
在那儿?

Answers:


19

根据文档PL / pgSQL Under the Hood,您可以plpgsql.variable_conflict在创建函数之前或在函数定义的开头使用配置参数,声明您希望如何解决此类冲突(3个可能的值为error(默认)use_variableuse_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
完善。我有na的感觉,我想念一些东西。我实际上记得过去曾经使用过它。谢谢!
Erwin Brandstetter
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.