sql - 函数调用的属性表示法给出错误

标签 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,由 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 forms f(x) and x.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 or UPDATE 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

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

关于sql - 函数调用的属性表示法给出错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56816432/

相关文章:

hibernate - 使用 JPQL/HQL 查询分层数据

sql - 需要根据列值分配不同的JSON数据结构

Postgresql 11 根据外键关系中主表中的列对详细表进行分区

sql - 按年份统计的员 worker 数

sql - 为每个 Id 比较 PostgreSQL 中的不同行

MySQL SELECT 两个表,同时用第二个表的字段值替换第一个表的字段值

postgresql - 当我尝试连接到 Postgresql 时出现 panic

go - 如何查询和处理使用 go.uuid 创建并插入到 PostgreSQL 11 中的 UUID?

javascript - PHP 值重复两次

mysql - 表内的内连接