Sql 函数调用的属性表示法出现错误

Sql 函数调用的属性表示法出现错误,sql,postgresql,postgresql-11,Sql,Postgresql,Postgresql 11,当当前架构与函数的某个架构不同时,属性表示法函数调用会出错。 我创建了一个函数 CREATE FUNCTION pub.FullName(pub.reps) RETURNS text AS $func$ select ($1.fname || ' ' || $1.lname) $func$ LANGUAGE SQL; 我尝试使用属性表示法调用函数,如中所述: 但会收到一条错误消息: 使用函数表示法的查询工作正常: select pub.fullname(r.*) from p

当当前架构与函数的某个架构不同时,属性表示法函数调用会出错。

我创建了一个函数

CREATE FUNCTION pub.FullName(pub.reps)
  RETURNS text AS
$func$
       select ($1.fname || ' ' || $1.lname)
$func$ LANGUAGE SQL;
我尝试使用属性表示法调用函数,如中所述:

但会收到一条错误消息:

使用函数表示法的查询工作正常:

select pub.fullname(r.*) from pub.reps r;
数据库已通过备份/还原从PostgreSQL 10迁移

< >代码>选择版本()/<代码>:<代码> PostgreSQL 11.3,由VisualC++生成1914, 64位< /COD> < /P>
UPD。发现如果我将
pub
schema设置为默认值,则
从pub.reps中选择r.fullname r
不会出错。

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

所以Postgres没有找到这个函数。在这方面,11级和10级的研究生没有什么不同。不过,也有一些值得注意的相关发展。你提到:

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

请考虑以下文件中指出的这一细微变化:

  • 在消除函数与列引用之间的歧义时,请考虑语法形式(Tom Lane)

    x
    是表名或复合列时,PostgreSQL 传统上认为语法形式
    f(x)
    x.f
    是 等效,允许使用编写函数然后使用 它就像是一个按需计算的列。但是,如果两者都 解释是可行的,柱解释总是可行的 选择,如果用户希望 功能解释。现在,如果存在歧义,那么 选择符合句法形式的解释

因此,如果表
reps
中有一列
fullname
,以及您显示的函数
pub.fullname(pub.reps)
,则Postgres 10即使使用函数表示法,也会选择该列:

D为博士后准备的小提琴10

Postgres 11(更合理)选择了以下功能:

D博士后小提琴11

Postgres 12(目前为beta版)最终实现了真正生成的列

  • 添加对生成列的支持(Peter Eisentrut)
生成的列的内容是根据表达式计算的 (包括对同一表格中其他列的引用)而不是 由
INSERT
UPDATE
命令指定

不过,只有
存储的
生成的列进入了本版本。(在国际海事组织更有趣)。(目前还没有进入第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
);
小提琴

我声明了
fname
lname
notnull
。否则,您的简单连接(
fname | |“”| | lname
)就是一个陷阱。见:


在哪台服务器上测试数据库?为什么是大小写混合拼写?您是否在任何地方使用了双qoutes?混合大小写仅用于可读性。这不会影响结果。服务器与第一个数据库(我自己的笔记本电脑)相同。我发现它取决于当前的模式。如果我将pub模式设置为默认模式,那么
从pub.reps r中选择r.FullName即可。否则我会出错。@ErwinBrandstetter,谢谢您详细的回答和改进我的帖子。现在看起来好多了。也适用于dbfiddle链接。这应该是一个好工具。据我所知,如果不修改搜索路径(例如在查询中显式使用模式),就无法使用属性功能。因此,我最好等待Postgres 12。函数的模式必须位于搜索路径中,因为无法对属性进行模式限定(转换为函数)。严格地说,您不必修改
search\u路径
:您始终可以在已经存在的模式中创建函数,
pg\u catalog
,作为最后的手段。(尽管我宁愿避免将用户对象放在那里。)
select pub.fullname(r.*) from pub.reps r;
SELECT fullname(r) FROM reps r;  -- resolves to column if it exists, ignoring function
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
);