当前模式与功能之一不同时,属性表示法函数调用会出错。
我创建了一个函数
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
Select version()
PostgreSQL 11.3, compiled by Visual C++ build 1914, 64-bit
UPD 。发现如果我将pub架构设置为默认值,则select r.fullname from pub.reps r可以正常工作。
pub
select r.fullname from pub.reps r
您自己找到了问题的根源。确切地说:函数的模式pub必须在current中的 任何位置 列出 search_path ,而不必是“默认”或“当前”模式(列表中的第一个)。
search_path
因此Postgres找不到该功能。在这方面,Postgres 11与Postgres 10并无不同。但是,还有一些值得注意的相关发展。您提到:
考虑一下Postgres 11发行说明中指出的这一细微变化:
在对函数和列引用进行歧义消除时,请考虑语法形式(Tom Lane) 当 x 是表名或组合列时,PostgreSQL传统上将语法形式考虑为等价形式, f(x) 并且 x.f 允许使用诸如写函数然后将其当作按需计算列之类的技巧。但是,如果两种解释都是可行的,则始终选择列解释,如果用户打算使用函数解释,则会导致令人惊讶的结果。现在,如果存在歧义,则选择与句法形式匹配的解释。
当 x 是表名或组合列时,PostgreSQL传统上将语法形式考虑为等价形式, f(x) 并且 x.f 允许使用诸如写函数然后将其当作按需计算列之类的技巧。但是,如果两种解释都是可行的,则始终选择列解释,如果用户打算使用函数解释,则会导致令人惊讶的结果。现在,如果存在歧义,则选择与句法形式匹配的解释。
x
f(x)
x.f
因此, 如果fullname表中有一列reps 并且还pub.fullname(pub.reps)显示了功能,则即使使用功能符号,Postgres 10仍会选择该 列 :
fullname
reps
pub.fullname(pub.reps)
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) 生成的列的内容是根据表达式(包括对同一表中其他列的引用)计算得出的,而不是由INSERT或UPDATE命令指定的。
生成的列的内容是根据表达式(包括对同一表中其他列的引用)计算得出的,而不是由INSERT或UPDATE命令指定的。
INSERT
UPDATE
不过,只有 STORED 生成的列才包含在此发行版中。(更有趣的IMO) VIRTUAL 变体被推迟到以后的版本中。(尚未在Postgres 13中使用。)
STORED
VIRTUAL
您的表可能如下所示:
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 <>在这里拨弄
我声明了fname和lname栏NOT NULL。否则,您的简单串联(fname || ' ' || lname)是一个陷阱。
fname
lname
NOT NULL
fname || ' ' || lname