PostgreSQL - 类型的自动演员?

Ice*_*urn 3 postgresql

我正在努力将数据库从Firebird移植到PostgreSQL,并且有许多与类型转换相关的错误.例如,让我们采取一个简单的功能:

CREATE OR REPLACE FUNCTION f_Concat3 (
  s1 varchar, s2 varchar, s3 varchar
)
RETURNS varchar AS
$body$
BEGIN
   return s1||s2||s3;
END;
$body$ LANGUAGE 'plpgsql' IMMUTABLE CALLED ON NULL INPUT SECURITY INVOKER LEAKPROOF COST 100;
Run Code Online (Sandbox Code Playgroud)

由于Firebird对类型非常灵活,因此这些函数的调用方式不同:某些参数可能是另一种类型:整数/双精度/时间戳.当然在Postgres函数调用中f_Concat3 ('1', 2, 345.345)会导致如下错误:

函数f_Concat3(未知,整数,数字)未找到.

建议使用文档来使用如下的显式转换:

f_Concat3 ('1'::varchar, 2::varchar, 345.345::varchar) 
Run Code Online (Sandbox Code Playgroud)

此外,我可以为所有可能发生的类型组合创建一个函数克隆,它将起作用.解决错误的示例:

CREATE OR REPLACE FUNCTION f_Concat3 (
   s1 varchar, s2 integer, s3 numeric
)
RETURNS varchar AS
$body$
  BEGIN
    return s1::varchar||s2::varchar||s3::varchar;
  END;
Run Code Online (Sandbox Code Playgroud)

然而,这是非常糟糕和丑陋的,它不适用于大功能.

重要提示:我们为所有数据库提供了一个通用代码库,并使用我们自己的语言来创建包含选择查询的应用程序对象(表单,报表等).在函数调用上使用显式强制转换是不可能的,因为我们将失去与其他DB的兼容性.

我感到困惑的是,整型参数不能被浇铸成numericdouble precision,或date/ numberstring.我甚至面临的问题与integersmallint,反之亦然.大多数数据库都不是这样的.

这种情况有没有最好的做法?
有没有明确演员的替代方案?

Lau*_*lbe 5

SQL是一种类型化语言,PostgreSQL比其他关系数据库更重视.不幸的是,这意味着在使用草率编码移植应用程序时会付出额外的努力.

添加隐式强制转换是很诱人的,但文档会警告您在内置数据类型之间创建强制转换:

用户可以使用CREATE CAST命令添加其他强制转换.(这通常与定义新数据类型一起完成.内置类型之间的强制转换集经过精心设计,最好不要更改.)

这不是空闲警告,因为如果在现有类型之间创建新的强制转换,函数解析和其他事情可能会突然失败或行为异常.

我认为,如果你真的不想清理代码(这将使它在未来更加便携),你别无选择,只能添加更多版本的功能.

幸运的是,PostgreSQL具有函数重载功能,这使得这成为可能.

通过在函数定义中使用具有多态类型的一个参数,可以使工作更轻松,如下所示:

CREATE OR REPLACE FUNCTION f_concat3 (
   s1 text, s2 integer, s3 anyelement
) RETURNS text
   LANGUAGE sql IMMUTABLE LEAKPROOF AS
'SELECT f_concat3(s1, s2::text, s3::text)';
Run Code Online (Sandbox Code Playgroud)

但是,您不能使用多个anyelement参数,因为只有在所有这些参数属于同一类型时才会起作用.

如果使用函数重载,请注意不要创建会导致函数解析失败的歧义.