当当前架构与函数之一不同时,属性表示法函数调用会出错。
我创建了一个函数
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,由 Visual C++ build 1914 编译,64 位
UPD。发现如果我将 pub
架构设置为默认值,则 select r.fullname from pub.reps r
不会出现错误。
最佳答案
你自己找到了问题的根源。准确地说:函数 pub
的架构必须列出在当前 search_path
的任何地方,而不是必须是“默认”或“当前”模式(列表中的第一个)。相关:
所以Postgres没有找到这个函数。在这方面,Postgres 11 与 Postgres 10 没有什么不同。不过,也有一些值得注意的相关进展。您提到:
Database has been migrated from PostgreSQL 10 with backup/restore.
考虑 release notes for Postgres 11 中指出的这一微妙变化:
Consider syntactic form when disambiguating function versus column references (Tom Lane)
When
x
is a table name or composite column, PostgreSQL has traditionally considered the syntactic formsf(x)
andx.f
to be equivalent, allowing tricks such as writing a function and then using it as though it were a computed-on-demand column. However, if both interpretations are feasible, the column interpretation was always chosen, leading to surprising results if the user intended the function interpretation. Now, if there is ambiguity, the interpretation that matches the syntactic form is chosen.
因此,如果表reps
中有一列fullname
,还有函数pub .fullname(pub.reps)
你显示的,Postgres 10,即使使用函数符号,仍然会选择列:
SELECT fullname(r) FROM reps r; -- resolves to column if it exists, ignoring function
db<> fiddle here 对于 Postgres 10
Postgres 11(更合理)选择了函数:
db<> fiddle here 对于 Postgres 11
Postgres 12(当前测试版)最终实现了真正的生成列。 The release notes:
- Add support for generated columns (Peter Eisentraut)
The content of generated columns are computed from expressions (including references to other columns in the same table) rather than being specified by
INSERT
orUPDATE
commands.
不过,只有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<> fiddle here
我声明了fname
和lname
列NOT NULL
。否则,您的简单串联 (fname || ' ' || lname
) 就是一个陷阱。请参阅:
关于sql - 函数调用的属性表示法给出错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56816432/