小编典典

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

sql

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

我创建了一个函数

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可以正常工作。


阅读 180

收藏
2021-04-14

共1个答案

小编典典

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

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

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

考虑一下Postgres
11发行说明中
指出的这一细微变化:

  • 在对函数和列引用进行歧义消除时,请考虑语法形式(Tom Lane)

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
<>在此处

拨弄 Postgres 10

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

db
<>在此处

拨弄 Postgres 11

Postgres 12
(当前为beta)最终实现了真正生成的列。发行说明:

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

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

不过,只有 STORED 生成的列才包含在此发行版中。(更有趣的IMO) VIRTUAL
变体被推迟到以后的版本中
。(尚未在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
<>在这里拨弄

我声明了fnamelnameNOT NULL。否则,您的简单串联(fname || ' ' || lname)是一个陷阱。

2021-04-14