是否可能溢出Oracle NUMBER类型?

时间:2013-03-18 18:49:53

标签: oracle plsql

我正在使用名为Appworx的流程调度软件。在其中,每个进程和子进程可以具有任意数量的“条件”,如果为真,则采取一些条件操作。

可能的条件操作之一是goto语句,其中普通整数是标签(每个条件从1开始编号)。我想使用此功能在循环中评估和运行一些任务,但你只能转到更高编号的条件(不要问我为什么......这似乎毁了大多数实用工具)。

我有理由相信所有这些都是由Oracle在后端评估的。看了Appworx的架构,似乎 goto 标签都是NUMBER(12,0)。我怀疑检查标签是否低于当前条件的逻辑类似于:

where label > current_condition

所以,如果我要提供一个足够高的goto,我认为它会欺骗检查并允许我做简单的循环。至少如果Oracle使用普通整数。是否有可能溢出它们,我将使用什么值将值溢出回1?

我认为Oracle版本很重要,如果是的话,它是11g。

PS此外,如果有人愿意为我重新标记这个,请添加“appworx”

2 个答案:

答案 0 :(得分:3)

Oracle数字实际上是具有40位十进制数字有效数的浮点数 所以,他们不能溢出来。

(10 ^ 40-1)是可以增加1的最大整数 proof

NUMBER(12,0)是NUMBER类型的子类型 也就是说,它由NUMBER类型和限制检查器组成。

答案 1 :(得分:2)

那么,这取决于你对'溢出'的定义。如果您将'溢出'定义为'找到值 n ,其中 n + 1< n ',然后不,没有这样的价值。如果你将'overflow'定义为'引发异常',那么是的,很可能对引发异常的NUMBER(12,0)执行操作。

运行以下命令:

DECLARE
  n  NUMBER(12, 0);
BEGIN
  n := 999999999999;  -- Twelve 9's
  DBMS_OUTPUT.PUT_LINE('1 : n=' || n);
  n := n + 1;
  DBMS_OUTPUT.PUT_LINE('2 : n=' || n);
EXCEPTION
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE('Exception: ' || SQLCODE || '  ' || SQLERRM);
END;

如您所见,尝试执行“n:= n + 1”时会抛出以下异常:

ORA-06502: PL/SQL: numeric or value error: number precision too large

因此很有可能溢出NUMBER的子类型。但是,鉴于您希望找到值 n ,其中 n + 1< n ,我认为你运气不好。

如果您真的想使用基本NUMBER类型激发此行为,请执行

n := POWER(10, 126);

当然,对于NUMBER中真正的 令人讨厌的 行为,您需要让它生成NaN(非数字):

n := 9999999999999999999999999999999999999999 * POWER(10, 125);
DBMS_OUTPUT.PUT_LINE('n=' || n);

产生

n=~

WTF?!? '〜'?到底是什么'〜'?好吧,这似乎是甲骨文打印NaN的方式。真正的有趣部分?一旦你在变量中得到NaN,你对该变量执行的任何操作都将产生另一个NaN。悄悄。默默。没有警告。没有追索权。尝试:

DBMS_OUTPUT.PUT_LINE('n * 1234=' || n * 1234);  -- produces n * 1234=~
DBMS_OUTPUT.PUT_LINE('n / 5678=' || n / 5678);  -- produces n / 5678=~
嘿 - 玩得很开心! : - )

在实际操作中,你不太可能遇到这种行为,但这是你真正需要注意的事情 - 不仅因为遇到它可能真的毁了你的月份,而是因为(你可以指望这个)下周卫生间立方体中一个无能为力的家伙会问这个问题 - 现在会知道这一切。 (而且你现在能够轻松,舒适地知道这个家伙真的 无能为力,因此应该停在The Cube From Hell。我的意思是,你在StackOverflow上接受了这个,对吧?那有多难?: - )

分享并享受。