由 bitand 错误引发的测试

[复制链接]
查看11 | 回复5 | 2008-2-13 12:43:03 | 显示全部楼层 |阅读模式
今天在用 bitand 时遇到一个错误: ORA-01426: numeric overflow
做了几个测试, 有兴趣的朋友探讨下:
test1 和 test2 表明 pl/sql 中最大处理的数值貌似是 power(2, 31)-1.
test3 证明 pl/sql 中是可以处理大于 power(2, 31)-1 的数值的.
猜测:
test1 和 test2 使用 pl/sql 引擎 编译的
test3 用SQL 引擎 编译的
依据:
1. 在SQL 中 integer 等同于 number(38).
SQL> create table aaa(a integer);
Table created.
SQL> desc aaa;
Name
Null?Type
----------------------------------------- -------- ------------------
A
NUMBER(38)

2. oracle 文档描述函数 BITAND
BITAND(argument1,argument2)

BITAND computes an AND operation on the bits of argument1 and argument2,

both of which must resolve to nonnegative integers, and returns an integer


oracle 说bitand 返回的是 integer, 这个integer 应该就是pl/sql 中的数据类型
----------------------------------------------------------------------
test1:
SQL> set serveroutput on;
SQL> declare
2 v_tmp number;
3begin
4 v_tmp := power(2, 31)-1; -- power(2, 31)-1 是允许的最大值
5 v_tmp := bitand(v_tmp, v_tmp);
6 dbms_output.put_line('v_tmp is ======>'||v_tmp);
7end;
8/
v_tmp is ======>2147483647
PL/SQL procedure successfully completed.
----------------------------------------------------------------------
test2:
SQL> set serveroutput on;
SQL> declare
2 v_tmp number;
3begin
4 v_tmp := power(2, 31);
5 v_tmp := bitand(v_tmp, v_tmp);
6 dbms_output.put_line('v_tmp is ======>'||v_tmp);
7end;
8/
declare
*
ERROR at line 1:
ORA-01426: numeric overflow
ORA-06512: at line 5
----------------------------------------------------------------------
test 3:
SQL> set serveroutput on;
SQL> declare
2 v_tmp number;
3begin
4 v_tmp := power(2, 31);
5 select bitand(v_tmp, v_tmp) into v_tmp from dual;
6 dbms_output.put_line('v_tmp is ======>'||v_tmp);
7end;
8/
v_tmp is ======>2147483648
PL/SQL procedure successfully completed.
回复

使用道具 举报

千问 | 2008-2-13 12:43:03 | 显示全部楼层
从test1, test2, test4 和 test5 可以得到 pl/sql 中 integer 的范围是 [-(power(2, 31)-1),power(2, 31)-1]
----------------------------------------------------------------------
test4:
SQL> set serveroutput on;
SQL> declare
2 v_tmp number;
3begin
4 v_tmp := -power(2, 31);
5 v_tmp := bitand(v_tmp, v_tmp);
6 dbms_output.put_line('v_tmp is ======>'||v_tmp);
7end;
8/
declare
*
ERROR at line 1:
ORA-01426: numeric overflow
ORA-06512: at line 5
----------------------------------------------------------------------
test5
SQL> set serveroutput on;
SQL> declare
2 v_tmp number;
3begin
4 v_tmp := -(power(2, 31)-1);
5 v_tmp := bitand(v_tmp, v_tmp);
6 dbms_output.put_line('v_tmp is ======>'||v_tmp);
7end;
8/
v_tmp is ======>-2147483647
PL/SQL procedure successfully completed.
回复

使用道具 举报

千问 | 2008-2-13 12:43:03 | 显示全部楼层
准确的说应该是pl/sql中对int类型采用了C语言的无符号整形定义导致。
c语言的unsigned int型可以表示2^32,而包含正负整数,就各表示一半。所以这个数值会溢出也是可以理解的。



回复

使用道具 举报

千问 | 2008-2-13 12:43:03 | 显示全部楼层
c语言的unsigned int 范围是 0~2^16, 不是2^32, :d
但你说的道理也许是对的, 在pl/sql 中 oracle 利用类似的数据结构来实现的。
一个问题就是, oracle 在 pl/sql 语句块中何时使用 SQL 中的数据结构, 何时有切换到 pl/sql中, 有没有什么办法知道 oracle 是怎么做的?
感谢关注。
回复

使用道具 举报

千问 | 2008-2-13 12:43:03 | 显示全部楼层
根据原码,反码,补码的数据规则,正数的原补反码都是补存在符号位的问题,负数做位运算的时候是根据产生的补码来做运算的,出现溢出的情行是正常的,所以 must resolve to nonnegative integers
回复

使用道具 举报

千问 | 2008-2-13 12:43:03 | 显示全部楼层
最初由 zmisi 发布
[B]c语言的unsigned int 范围是 0~2^16, 不是2^32, :d
但你说的道理也许是对的, 在pl/sql 中 oracle 利用类似的数据结构来实现的。
一个问题就是, oracle 在 pl/sql 语句块中何时使用 SQL 中的数据结构, 何时有切换到 pl/sql中, 有没有什么办法知道 oracle 是怎么做的?
感谢关注。 [/B]


我少说了一句:是采用了32位的unsigned int

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题

0

回帖

4882万

积分

论坛元老

Rank: 8Rank: 8

积分
48824836
热门排行