问题现象
OceanBase 数据库 V4.x 集群,PL 内存在使用绑定变量的方式执行动态 SQL 时,出现如下异常。
obclient [SYS]> call TEST('1234');
ORA-00932: inconsistent datatypes
at SYS.TEST, line : 17, col : 3
且伴随出现如下日志。
[2025-03-07 10:42:33.515437] WDIAG [SQL.ENG] aggregate_result_type_for_case (ob_expr_operator.cpp:1075) [60142][T1002_L0_G0][T1002][xxxxx-xxxxx-xxxxx-xxxxx] [lt=5][errcode=-5083] fail to judge same type(i=1, res_type={meta:{type:"DATE", collation:"binary", coercibility:"NUMERIC"}, accuracy:{length:-1, precision:19, scale:0}, flag:0, calc_type:{type:"DATE", collation:"binary", coercibility:"NUMERIC"}}, types[i]={meta:{type:"CHAR", collation:"utf8mb4_bin", coercibility:"IMPLICIT"}, accuracy:{length:2000, precision:2, scale:-1}, flag:0, calc_type:{type:"CHAR", collation:"utf8mb4_bin", coercibility:"IMPLICIT"}}, ret=-5083)
[2025-03-07 10:42:33.515461] WDIAG [SQL.ENG] calc_result_typeN (ob_expr_case.cpp:79) [60142][T1002_L0_G0][T1002][xxxxx-xxxxx-xxxxx-xxxxx] [lt=22][errcode=-5083] failed to aggregate result type
关键日志信息如下。
[2025-03-07 10:42:33.515437] WDIAG [SQL.ENG] aggregate_result_type_for_case (ob_expr_operator.cpp:1075) [60142][T1002_L0_G0][T1002][xxxxx-xxxxx-xxxxx-xxxxx] [lt=5][errcode=-5083] fail to judge same type(i=1, res_type={meta:{type:"DATE", collation:"binary", coercibility:"NUMERIC"}, accuracy:{length:-1, precision:19, scale:0}, flag:0, calc_type:{type:"DATE", collation:"binary", coercibility:"NUMERIC"}}, types[i]={meta:{type:"CHAR", collation:"utf8mb4_bin", coercibility:"IMPLICIT"}, accuracy:{length:2000, precision:2, scale:-1}, flag:0, calc_type:{type:"CHAR", collation:"utf8mb4_bin", coercibility:"IMPLICIT"}}, ret=-5083)
问题原因
该问题是 OceanBase 数据库在对 PL 内 SQL 语句的部分列表达式或变量进行类型推导时,推导出了错误的类型导致,属于 OceanBase 产品缺陷。
问题的风险及影响
无法正常执行 PL。
适用版本
OceanBase 数据库 V4.x 版本。
解决方法
升级至问题已修复版本。目前已修复的版本包括 OceanBase 数据库 V4.2.5 GA(oceanbase-4.2.5.0-100000082024102022)及之后版本。
定位到 PL 内的异常行,尝试通过在 SQL 语句内添加 CAST 等函数手动转换为所需类型。
示例如下。
V_SQL := 'INSERT INTO T_CPMS_AR_MA_BIZ (PK_ID, START_DATE, END_DATE, UPDATE_TIME) SELECT SEQ_T_CPMS_AR_MA_BIZ_ID.NEXTVAL, '; -- 使用绑定变量方式 V_SQL := V_SQL || 'CASE WHEN MA.PK_ID IS NOT NULL THEN MA.START_DATE ELSE cast(:1 as date) END, '; V_SQL := V_SQL || 'CASE WHEN MA.PK_ID IS NOT NULL THEN MA.END_DATE ELSE cast(:2 as date) END, '; V_SQL := V_SQL || ':3 FROM M_CPMS_AR_MA_BIZ_TMP MA';