函数调用的属性符号给出错误

时间:2019-06-29 09:23:02

标签: sql postgresql postgresql-11

当当前模式不同于函数之一时,属性表示法函数调用会出错。

我创建了一个函数

CREATE FUNCTION pub.FullName(pub.reps)
  RETURNS text AS
$func$
       select ($1.fname || ' ' || $1.lname)
$func$ LANGUAGE SQL;

我正在尝试使用docs中所述的带有属性符号的函数:

select r.fullname from pub.reps r;

但是收到错误消息:

ERROR:  column "fullname" does not exist

带有功能符号的查询工作正常:

select pub.fullname(r.*) from pub.reps r;

数据库已通过备份/还原从PostgreSQL 10迁移。

Select version()给出:PostgreSQL 11.3, compiled by Visual C++ build 1914, 64-bit

UPD 。发现如果我将pub模式设置为默认模式,那么select r.fullname from pub.reps r可以正常工作。

1 个答案:

答案 0 :(得分:2)

您自己找到了问题的根源。确切地说:函数pub的架构必须在当前 search_path 中的任意位置列出 ,而不必是“默认”或“当前”模式(列表中的第一个)。相关:

因此Postgres找不到该功能。在这方面,Postgres 11与Postgres 10并无不同。但是,还有一些值得注意的相关发展。您提到:

  

数据库已通过备份/还原从PostgreSQL 10迁移。

考虑release notes for Postgres 11中指出的细微变化:

  
      
  • 在对函数和列引用进行歧义时考虑语法形式(汤姆巷)

         

    x 是表名或组合列时,PostgreSQL具有   传统上将 f(x) x.f 视为句法形式   等效,允许诸如编写函数然后使用的技巧   好像它是按需计算列。但是,如果两者   解释是可行的,列解释总是   选择,如果用户打算   功能解释。现在,如果有歧义,   选择与句法形式匹配的解释。

  •   

因此,如果在表fullname中有列reps,并且您显示的函数pub.fullname(pub.reps)是Postgres 10, ,即使具有功能符号,仍会选择

SELECT fullname(r) FROM reps r;  -- resolves to column if it exists, ignoring function

db <>小提琴here for Postgres 10

Postgres 11(更合理地)选择功能:

db <>小提琴here for Postgres 11

Postgres 12 (当前为beta)最终实现了真正生成的列。 The release notes:

  
      
  • 添加对生成的列的支持(Peter Eisentraut)
  •   
     

根据表达式计算生成的列的内容   (包括对同一表中其他列的引用),而不是   由INSERTUPDATE命令指定。

不过

只有 STORED 生成的列才包含在此版本中。 (更有趣的IMO)VIRTUAL variant was postponed for a later release。希望获得Postgres 13。

您的表可能如下所示:

CREATE TABLE pub.reps (
  reps_id  int GENERATED ALWAYS AS IDENTITY PRIMARY KEY 
, fname    text NOT NULL
, lname    text NOT NULL
, fullname text GENERATED ALWAYS AS (fname || ' ' || lname) STORED
);

db <>提琴here

我声明了fnamelname列。否则,您的简单串联(NOT NULL)是一个陷阱。参见: