函数调用的属性符号给出错误 [英] Attribute notation for function call gives error

查看:98
本文介绍了函数调用的属性符号给出错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我已经创建了一个函数

 创建功能pub.FullName(pub.reps)
返回文本为
$ func $
select( $ 1.fname ||''|| $ 1.lname)
$ func $语言SQL;

我正在尝试使用文档):

 从pub.reps r中选择r.fullname; 

但是收到错误消息:


 错误:列全名不存在




使用功能符号进行查询可以正常工作:

 选择pub.fullname(r。 *)来自pub.reps r; 

数据库已从PostgreSQL 10进行了备份/恢复。



选择版本()给出: PostgreSQL 11.3,由Visual C ++ build 1914编译,64位



UPD 。发现,如果我将 pub 模式设置为默认模式,那么从pub.reps r 中选择r.fullname可以不使用错误。

解决方案

您自己找到了问题的根源。确切地说:函数 pub 的模式必须在当前 search_path ,不必是默认或当前架构(列表中的第一个)。相关:





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


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


请考虑 Postgres 11发行说明



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



    x 是表名或复合列,PostgreSQL通常将
    视为语法形式 f(x) xf 等同于
    ,允许使用诸如函数,然后使用
    就像是按需计算列。但是,如果两种
    解释都是可行的,则总是选择
    进行列解释,如果用户打算使用
    函数解释,则会导致令人惊讶的结果。现在,如果存在歧义,则选择与语法形式匹配的
    解释。



因此,如果,表 reps 中有一列全名 以及您显示的函数 pub.fullname(pub.reps),即使具有功能符号,Postgres 10仍会选择

 从代表r中选择全名(r); -解析到是否存在的列,忽略函数

db<> fiddle 此处 对于Postgres 10



Postgres 11(更合理地)选择函数:



db<> fiddle 此处 for Postgres 11



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



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



生成的列的内容是根据表达式
(包括对同一表中其他列的引用)计算的,而不是由 INSERT <指定的
/ code>或 UPDATE 命令。


不过, STORED 生成的列已纳入此发行版。 (更有趣的IMO) 虚拟 变体被推迟到以后的版本中。 (尚未在Postgres 13中使用。)



您的表格可能看起来像这样:

  CREATE TABLE pub.reps(
reps_id int始终以身份主键
生成,fname文本NOT NULL
,lname文本NOT NULL
,全名文本始终生成AS(fname ||'''|| lname)存储
);

db<>小提琴此处



我声明了 fname lname NOT NULL 。另外,您的简单串联( fname ||’’|| lname )是一个陷阱。请参阅:




Attribute notation function call gives error when current schema is different from one of function.

I have created a function

CREATE FUNCTION pub.FullName(pub.reps)
  RETURNS text AS
$func$
       select ($1.fname || ' ' || $1.lname)
$func$ LANGUAGE SQL;

I am trying to call the function with attribute notation as described in docs):

select r.fullname from pub.reps r;

But get an error message:

ERROR:  column "fullname" does not exist

Query with functional notation works fine:

select pub.fullname(r.*) from pub.reps r;

Database has been migrated from PostgreSQL 10 with backup/restore.

Select version() gives: PostgreSQL 11.3, compiled by Visual C++ build 1914, 64-bit

UPD. Found out that if I set pub schema as default, then select r.fullname from pub.reps r works with no error.

解决方案

You found the root of the problem yourself. To be precise: the schema of the function pub has to be listed anywhere in the current search_path, does not have to be the "default" or "current" schema (the first one in the list). Related:

So Postgres did not find the function. Postgres 11 isn't different from Postgres 10 in this regard. There are some noteworthy, related developments, though. You mentioned:

Database has been migrated from PostgreSQL 10 with backup/restore.

Consider this subtle change pointed out in the 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.

So, if there was a column fullname in table reps and also the function pub.fullname(pub.reps) you display, Postgres 10, even with functional notation, would still chose the column:

SELECT fullname(r) FROM reps r;  -- resolves to column if it exists, ignoring function

db<>fiddle here for Postgres 10

Postgres 11 (more reasonably) choses the function:

db<>fiddle here for Postgres 11

Postgres 12 (currently beta) eventually implements true generated columns. 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.

Only STORED generated columns made it into this release, though. The (more interesting IMO) VIRTUAL variant was postponed for a later release. (Not in Postgres 13, yet.)

Your table could look like this:

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

I declared fname and lname columns NOT NULL. Else, your simple concatenation (fname || ' ' || lname) is a trap. See:

这篇关于函数调用的属性符号给出错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆