适用版本
OceanBase 数据库 V2.x 和 V3.x 版本。
问题描述
OceanBase 数据库 MySQL 和 Oracle 租户下创建与系统函数同名的自定义函数,程序调用时会调用系统函数而不是自定义函数。
以下用 MySQL 租户来举例说明。
MySQL 默认不支持 NVL 函数,OceanBase 数据库 MySQL 模式实现了该函数。如果有 UDF 使用了 NVL 名字,创建会成功,但是调用会用 OceanBase 数据库的内置函数覆盖同名的自定义函数。
问题复现如下。
obclient [db_mysql]> CREATE
FUNCTION `db_mysql`.`nvl`(
f1 varchar(200),
f2 varchar(200))
RETURNS varchar(200)
BEGIN
if f1 is null then
return concat('NULL:',f2);
else
return concat('F1:',f1,",F2:",f2);
end if;
END
/
Query OK, 0 rows affected (0.081 sec)
obclient [db_mysql]> DELIMITER ;
obclient [db_mysql]> select nvl(null,'10'),nvl(20,'10');
输出结果如下。
+----------------+--------------+
| nvl(null,'10') | nvl(20,'10') |
+----------------+--------------+
| 10 | 20 |
+----------------+--------------+
1 row in set (0.001 sec)
问题原因
OceanBase 数据库 MySQL 和 Oracle 租户下创建与系统函数同名的自定义函数,程序调用时会调用系统函数而不是自定义函数。
解决方法
应该避免此类场景。
如果功能一样可以直接使用,如果功能不一致,需要将原函数改名迁移,业务做相应适配。此例中,函数 NVL 和内置函数名字一样,功能不一样,需要改名方可。
obclient [db_mysql]> drop function nvl;
Query OK, 0 rows affected (0.124 sec)
obclient [db_mysql]> DELIMITER $$
obclient [db_mysql]> CREATE
FUNCTION `db_mysql`.`nvl_new`(
f1 varchar(200),
f2 varchar(200))
RETURNS varchar(200)
BEGIN
if f1 is null then
return concat('NULL:',f2);
else
return concat('F1:',f1,",F2:",f2);
end if;
END
/
Query OK, 0 rows affected (0.096 sec)
obclient [db_mysql]> DELIMITER ;
obclient [db_mysql]> select nvl(null,'10'),nvl(20,'10');
输出结果如下。
+----------------+--------------+
| nvl(null,'10') | nvl(20,'10') |
+----------------+--------------+
| 10 | 20 |
+----------------+--------------+
1 row in set (0.001 sec)
obclient [db_mysql]> select nvl_new(null,'10'),nvl_new(20,'10');
输出结果如下。
+--------------------+------------------+
| nvl_new(null,'10') | nvl_new(20,'10') |
+--------------------+------------------+
| NULL:10 | F1:20,F2:10 |
+--------------------+------------------+
1 row in set (0.026 sec)