当函数与当前模式不同时,属性表示法调用函数报错
我之前在PostgreSQL版本迁移时也踩过类似的坑,结合你描述的场景,咱们来拆解下问题根源和解决方案:
问题本质
你创建的pub.FullName(pub.reps)函数归属pub模式,而属性表示法(r.fullname)在解析时,会依赖当前数据库的search_path(搜索路径)来匹配对应函数。当pub不在默认搜索路径里时,PostgreSQL找不到这个函数,就会误把它当成表的列,从而抛出column "fullname" does not exist的错误。
而函数表示法(pub.fullname(r.*))因为明确指定了函数所在的模式,不管搜索路径如何都能精准定位,所以可以正常执行。你提到把pub设为默认模式后属性表示法恢复正常,也正好验证了这一点——此时pub被加入搜索路径,PostgreSQL能找到对应的函数了。
可行解决方案
针对这个问题,有两种实用的处理方式:
修改用户默认搜索路径(推荐)
把pub模式加入到数据库用户的默认搜索路径中,这样每次连接数据库时都会自动包含该模式,属性表示法就能正常工作了。执行以下SQL(替换your_username为实际数据库用户名):ALTER ROLE your_username SET search_path TO "$user", pub, public;执行完成后需要重新连接数据库,配置才会生效。
显式指定类型所属模式(替代方案)
如果你不想修改全局搜索路径,也可以通过给表类型指定模式的方式调用,只是写法稍显繁琐:select (r::pub.reps).fullname from pub.reps r;
另外补充个小细节:PostgreSQL 10到11的迭代中,属性表示法的核心逻辑没有大改,但备份恢复过程中可能没正确还原原有的search_path配置,导致迁移后出现这个问题。你可以执行SHOW search_path;查看当前搜索路径,确认pub是否在列表中。
内容的提问来源于stack exchange,提问作者Leo

