经BabelfishCompass验证的SQL函数无法通过PostgreSQL访问咨询
Babelfish跨端口函数调用问题及解决方案
问题背景
- 环境:多数据库模式(multiple_db)的Babelfish集群
- 操作:在SSMS通过1433端口创建
[dbo].[GetRef]函数,经BabelfishCompass分析验证通过 - 现象:SSMS调用函数完全正常,但在PgAdmin通过5432端口执行PostgreSQL风格的查询时,出现架构未识别错误
相关代码与错误信息
函数定义(SQL Server语法)
CREATE FUNCTION [dbo].[GetRef] ( @Id bigint ) RETURNS TABLE AS RETURN ( SELECT TOP 1 ID, MUTID, FINID FROM [dbo].[Ref] WHERE ToBeInserted = 1 AND ID > @Id ORDER BY REFID )
PostgreSQL端查询语句
SELECT MyDatabase_dbo.getref(1)
错误信息
ERROR: relation "dbo.ref" does not exist LINE 2: FROM [dbo].[Ref] ^ QUERY: SELECT TOP 1 ID, MUTID, FINID FROM [dbo].[Ref] WHERE ToBeInserted = 1 AND ID > @Id ORDER BY REFID CONTEXT: PL/tsql function MyDatabase_dbo.getref(bigint) line 3 at RETURN QUERY
核心问题解答
1. 为SQL Server编写的函数能否通过PostgreSQL端访问?
你的理解是正确的,Babelfish的设计初衷就是让SQL Server兼容对象(函数、存储过程等)可以同时通过SQL Server兼容端口(1433)和PostgreSQL原生端口(5432)访问,但要注意多数据库模式下的对象命名映射规则。
2. 是否必须修改架构名才能在PostgreSQL端运行?
不需要手动修改函数内的架构引用。问题根源在于多数据库模式下,Babelfish会把SQL Server的[数据库名].[架构名].[对象名]映射为PostgreSQL的数据库名_架构名.对象名格式,但函数执行时的**搜索路径(search_path)**未包含对应的映射架构,导致无法识别dbo.Ref。
可以通过两种方式解决:
- 临时方案:在PgAdmin执行查询前,先设置搜索路径包含映射后的架构:
SET search_path TO MyDatabase_dbo, public; SELECT MyDatabase_dbo.getref(1); - 持久化方案:修改PostgreSQL登录角色的默认搜索路径,将映射架构加入:
ALTER ROLE your_login_role SET search_path TO MyDatabase_dbo, public;
3. 3000多个函数/存储过程的情况下,外部应用该用哪个端口?
取决于你的应用类型:
- 如果是原SQL Server应用,或者需要完全兼容SQL Server语法(比如使用
TOP、@变量等),优先用1433端口,无需修改任何代码,直接复用原SQL Server的访问逻辑,迁移成本最低。 - 如果是PostgreSQL原生应用,或者需要结合PostgreSQL原生特性(比如JSONB、高级CTE用法),可以用5432端口,但要注意对象命名的映射规则,提前配置好正确的搜索路径。
针对你有大量SQL Server兼容对象的场景,强烈推荐使用1433端口,避免修改现有函数、存储过程的代码,也省去架构映射的额外配置工作。
内容的提问来源于stack exchange,提问作者Bachir ATMANI
相关产品推荐
相关产品推荐

