立即执行调用时出现错误数字溢出oracle

问题描述

我定义了一个将公式(类型值为String)解析为数值的过程: 公式中的某些case值可能会执行或引发错误数字溢出。 代码

DECLARE
    formula VARCHAR2(1000) := '1111111111 * 2';
    val NUMBER;
BEGIN
    EXECUTE IMMEDIATE 'BEGIN :res := '||formula||'; END;' USING OUT val;
    DBMS_OUTPUT.PUT_LINE ( 'formula = ' || formula );
    DBMS_OUTPUT.PUT_LINE ( 'val = ' || val );
END;

在这种情况下,请引发错误数字溢出。当我将值操作数增加/少于10个字符1时,它将正常工作。

如果公式中的值包含数字1,我​​会尝试检查一些值并查看大多数错误。 是这个原因吗?

谢谢大家!

解决方法

在PL / SQL中将整数相乘时,实际上是在使用pls_integers

pls_integer有2,147,483,647的上限,在您的示例2,222,222中使用的乘法超过此上限,从而导致数字溢出。

从官方文档以及从Ask Tom网站获取:

即使将结果分配给NUMBER数据类型,具有两个PLS_INTEGER值的计算也会溢出PLS_INTEGER范围,从而引发溢出异常。

要摆脱这种情况,我们可以将表达式中的值之一设为数字。

案例1:使用CAST

DECLARE
    formula VARCHAR2(1000) := 'cast(1111111111 as number) * 2';
    val NUMBER;
BEGIN
    EXECUTE IMMEDIATE
    'BEGIN '||
    ' :res := '||formula||';'||
    'END;' USING OUT val;
    DBMS_OUTPUT.PUT_LINE ( 'formula = ' || formula );
    DBMS_OUTPUT.PUT_LINE ( 'val = ' || val );
END;
/

案例2:将表达式之一设为十进制,Oracle会将其隐式转换为数字

DECLARE
    formula VARCHAR2(1000) := '1111111111 * 2.0';
    val NUMBER;
BEGIN
    EXECUTE IMMEDIATE
    'BEGIN '||
    ' :res := '||formula||';'||
    'END;' USING OUT val;
    DBMS_OUTPUT.PUT_LINE ( 'formula = ' || formula );
    DBMS_OUTPUT.PUT_LINE ( 'val = ' || val );
END;
/