官方教程中的Working with Numbers in PL/SQL篇。
PL/SQL中的NUMBERS
-
NUMBER:十进制数据类型,适合用来处理金钱数量。是唯一一个实现了平台独立的数字类型。
-
PLS_INTEGER:PL/SQL特有的数据类型,所以不能把这种类型的数据存入数据库表中。它和机器硬件的结构和底层整数表示有关。
-
SIMPLE_INTEGER:这种数据类型可以显著缩短本地编译代码的执行时间。但是本篇文章不展开。
-
BINARY_FLOAT和BINARY_DOUBLE:单精度/双精度二进制浮点数据类型。在需要高精度运算时可以用来提高性能。
NUMBER
ORACLE与PL/SQL中最常见的数字数据类型,可以用来存放任意大小所有的整数、定点数、浮点数。它是基于平台独立实现的,所以无论在什么硬件平台上运行,计算后得到的结果都是相同的。
声明
l_salary NUMBER;
这个声明语句定义了一个浮点型数字。数据库最多分配40位空间,根据你赋的值小数点会浮动到最合适的地方。NUMBER变量能容纳的值的范围是10-130(1.0E-130)到10126-1(1.0E126-1),如果给变量赋值小于最小值,就向下设为0,如果大于最大值,就被设置为un-defined,造成运行时问题,但是不会抛出异常。
DECLARE
tiny_nbr NUMBER := 1e - 130;
test_nbr NUMBER;
-- 1111111111222222222233333333334
-- 1234567890123456789012345678901234567890
big_nbr NUMBER := 9.999999999999999999999999999999999999999e125;
-- 1111111111222222222233333333334444444
-- 1234567890123456789012345678901234567890123456
fmt_nbr VARCHAR2 ( 50 ) := '9.99999999999999999999999999999999999999999EEEE';
BEGIN
DBMS_OUTPUT.PUT_LINE ( 'tiny_nbr =' || TO_CHAR ( tiny_nbr ,'9.9999EEEE' ) ) ;
/* NUMBERs that are too small round down to zero. */
test_nbr := tiny_nbr / 1.0001;
DBMS_OUTPUT.PUT_LINE ( 'tiny made smaller =' || TO_CHAR ( test_nbr ,fmt_nbr ) ) ;
/* NUMBERs that are too large throw an error: */
DBMS_OUTPUT.PUT_LINE ( 'big_nbr =' || TO_CHAR ( big_nbr ,fmt_nbr ) ) ;
test_nbr := big_nbr * 1.0001; -- too big
DBMS_OUTPUT.PUT_LINE ( 'big made bigger =' || TO_CHAR ( test_nbr ,fmt_nbr ) ) ;
END;
----------------------
tiny_nbr = 1.0000E-130
tiny made smaller = .00000000000000000000000000000000000000000E+00
big_nbr = 9.99999999999999999999999999999999999999900E+125
big made bigger =#################################################
如果强行给NUMBER变量赋一个超过范围的值,就会引发numeric overflow或underflow exception,如果是通过计算产生的过大的值,就不会抛出异常。解决的方法是写一个alidation routines that anticipate out-of-range values,或者使用BINARY_DOUBLE
。但是使用二进制数据类型可能会发生四舍五入,所以要慎重考虑。
NUMBER (precision, scale)
限制变量的精度和标度。例如
price NUMBER (8, 2)
,它声明了一个定点数,这个数的有效位数是8位,其中小数点右边(正数时)或者左边(负数时)是2位,精度和标度都必须是整数。精度的范围是1到38,标度的范围是-87到127。声明定点数时,标度的值要小于精度的值。
PLS_INTEGER
PLS_INTEGER
存储从-2147483648到2147483647的有符号整数,数据显示与硬件平台的本地整数格式有关。
声明
loop_counter PLS_INTEGER;
专为速度而设计,在计算时使用PLS_INTEGER
的话,Oracle软件运用本地机器运算,计算速度比NUMBER快。
如果运算密集,设计整形运算且值不会超过合法范围的话,建议使用PLS_INTEGER
。如果在计算中会频繁与NUMBER类型进行转换的话,最好使用NUMBER。
内建方法
ROUND
将数字四舍五入成指定的位数,如果不指定,则将数字转换为最接近的整数。如果第二位参数是负数的话,就会被舍入为最接近的10^|decimals|。
BEGIN
DBMS_OUTPUT.put_line (ROUND (10.25));
DBMS_OUTPUT.put_line (ROUND (10.25, 1));
DBMS_OUTPUT.put_line (ROUND (10.23, 1));
DBMS_OUTPUT.put_line (ROUND (10.25, 2));
DBMS_OUTPUT.put_line (ROUND (10.25, -2));
DBMS_OUTPUT.put_line (ROUND (125, -1));
END;
---------------------
10
10.3
10.2
10.25
0
130
TRUNC
使用去尾法对数字进行转换。
BEGIN
DBMS_OUTPUT.put_line (TRUNC (10.23, 1));
DBMS_OUTPUT.put_line (TRUNC (10.25, 1));
DBMS_OUTPUT.put_line (TRUNC (123.456, -1));
DBMS_OUTPUT.put_line (TRUNC (123.456, -2));
END;
-------------------
10.2
10.2
120
100
FLOOR/CEIL
FLOOR返回小于等于指定数字的最小整数。
CEIL返回大于等于指定数字的最小整数。
BEGIN
DBMS_OUTPUT.put_line (FLOOR (1.5));
DBMS_OUTPUT.put_line (CEIL (1.5));
END;
----------
1
2
MOD/REMAINDER
都是取余计算,计算方式有些不同。
当两个参数的符号相同时:MOD (m, n) = m - n * FLOOR (m/n)
当符号不同时:MOD (m,n) = ( m - n * CEIL(m/n) )
REMAINDER(n1,n) = n2 - (n1*N), N是最接近n2/n1的整数,并且n1不为0。
BEGIN
DBMS_OUTPUT.put_line (MOD (15, 4));
DBMS_OUTPUT.put_line (MOD (-15, 4));
DBMS_OUTPUT.put_line (MOD (15, -4));
DBMS_OUTPUT.put_line (REMAINDER (15, 4));
DBMS_OUTPUT.put_line (MOD (15, 6));
DBMS_OUTPUT.put_line (REMAINDER (15, 6));
END;
----------------
3
-3
3
-1
3
3
TO_CAHR
将数字转化为字符串,只有一个参数的TO_CHAR只会将数字的有效部分转化。
加上第二个参数,即可进行有格式地转化。
- 9G999G999:G表示组分隔符,具体符号与本地语言设置有关。9表示这个地方应该显示有效数字或者空格。
- 0G000G999:0表示如果此处不是有效数字的话,就显示0。
- FM9G999G999:如果不想要空格或者0,就用FM元素。
- FML999G999D99:L指定本地货币符号的位置。D是小数点的位置。
BEGIN
DBMS_OUTPUT.put_line ( TO_CHAR ( 100.55 ) ) ;
DBMS_OUTPUT.put_line ( TO_CHAR ( 000100.5500 ) ) ;
DBMS_OUTPUT.put_line ( TO_CHAR ( 10000.00 ) ) ;
DBMS_OUTPUT.put_line ( 'Amount='|| TO_CHAR ( 10000 ,'9G999G999' ) ) ;
DBMS_OUTPUT.put_line ( 'Amount=' || TO_CHAR ( 10000 ,'0G000G999' ) ) ;
DBMS_OUTPUT.put_line ( 'Amount=' || TO_CHAR ( 10000 ,'FM9G999G999' ) ) ;
DBMS_OUTPUT.put_line ( 'Salary=' || TO_CHAR ( 14500.77 ,'FML999G999D99' ) ) ;
END;
--------------------
100.55
100.55
10000
Amount= 10,000
Amount= 0,010,000
Amount=10,000
Salary=\14,500.77
网友评论