我正在努力将数据库从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的兼容性.
我感到困惑的是,整型参数不能被浇铸成numeric或double precision,或date/ number到string.我甚至面临的问题与integer对smallint,反之亦然.大多数数据库都不是这样的.
这种情况有没有最好的做法?
有没有明确演员的替代方案?
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参数,因为只有在所有这些参数属于同一类型时才会起作用.
如果使用函数重载,请注意不要创建会导致函数解析失败的歧义.
| 归档时间: |
|
| 查看次数: |
3708 次 |
| 最近记录: |