PLSQL 中的 REAL 数据类型

Posted

技术标签:

【中文标题】PLSQL 中的 REAL 数据类型【英文标题】:REAL datatype in PLSQL 【发布时间】:2016-04-08 05:33:39 【问题描述】:
SET SERVEROUTPUT ON;
DECLARE
A REAL := 123456789123456789123456789123456789123456789123456789123456789123456789;
BEGIN
DBMS_OUTPUT.PUT_LINE('A Value is : ' || A);
END;

上面的程序运行并给了我如下的输出。

anonymous block completed
A Value is : 123456789123456789123456789123456789123500000000000000000000000000000000

谁能解释一下为什么它在第 40 位后显示 0 而不是实际值。还有第 40 位数字是 5 而不是 4。

【问题讨论】:

你猜到了吗? 先看文档:docs.oracle.com/cd/B19306_01/server.102/b14237/… 你读过the SQL Reference manual吗? "5 而不是 4。" --> 四舍五入可能有帮助:mathsisfun.com/rounding-numbers.html Oracle guarantees the portability of numbers with precision of up to 20 base-100 digits, which is equivalent to 39 or 40 decimal digits depending on the position of the decimal point。它显示了 40 个最重要的数字;最后一个是四舍五入的,剩下的数字为零,因为你已经超出了可用的精度。 【参考方案1】:

SQL language reference 表示“REAL 数据类型是二进制精度为 63 或十进制 18 的浮点数”,它显示为 FLOAT(63)。 FLOAT [(p)] 是:

精度为 p 的 NUMBER 数据类型的子类型。 FLOAT 值在内部表示为 NUMBER。精度 p 的范围可以从 1 到 126 个二进制数字。 FLOAT 值需要 1 到 22 个字节。

如果您创建具有 REAL 列的表,其行为类似于 FLOAT(63):

create table t42 (a real, b float(126), c float(63), d number);
insert into t42 (a, b, c, d)
values (123456789123456789123456789123456789123456789123456,
  123456789123456789123456789123456789123456789123456,
  123456789123456789123456789123456789123456789123456,
  123456789123456789123456789123456789123456789123456);

select a, b, c, d from t42;

                                                               A
----------------------------------------------------------------
                                                               B
----------------------------------------------------------------
                                                               C
----------------------------------------------------------------
                                                               D
----------------------------------------------------------------
             123456789123456789100000000000000000000000000000000 
             123456789123456789123456789123456789120000000000000 
             123456789123456789100000000000000000000000000000000 
             123456789123456789123456789123456789123000000000000

我使用了一个较小的值,因此它可以在 numformat 的 49 位 SQL*Plus/SQL Developer 限制内显示。请注意,FLOAT(126) 和 NUMBER 值与该值并不完全相同。

PL/SQL 略有不同。在标准包中可以看到:

  type NUMBER is NUMBER_BASE;
  subtype FLOAT is NUMBER; -- NUMBER(126)
  subtype REAL is FLOAT; -- FLOAT(63)

在 PL/SQL 块中,您的 REAL 变量可以采用不受限制的 NUMBER 可以采用的任何值,并且具有相同的比例/精度效果;在这种情况下,只保留最重要的(38-40) 数字,并将其余数字四舍五入为前 40 位数字中的最小数字。您的值的整体“大小”(作为 72 位数字)被保留,但您失去的精度超出了 Oracle 内部格式可以存储的精度。如果您具有与表示例相同的变量类型并将原始值放入:

DECLARE
  A REAL := 123456789123456789123456789123456789123456789123456789123456789123456789;
  B FLOAT(126) := 123456789123456789123456789123456789123456789123456789123456789123456789;
  c FLOAT(63) := 123456789123456789123456789123456789123456789123456789123456789123456789;
  D NUMBER := 123456789123456789123456789123456789123456789123456789123456789123456789;
BEGIN
  DBMS_OUTPUT.PUT_LINE('A Value is : ' || A);
  DBMS_OUTPUT.PUT_LINE('B Value is : ' || B);
  DBMS_OUTPUT.PUT_LINE('C Value is : ' || C);
  DBMS_OUTPUT.PUT_LINE('D Value is : ' || D);
END;
/

A Value is : 123456789123456789123456789123456789123500000000000000000000000000000000
B Value is : 123456789123456789123456789123456789120000000000000000000000000000000000
C Value is : 123456789123456789100000000000000000000000000000000000000000000000000000
D Value is : 123456789123456789123456789123456789123500000000000000000000000000000000

注意这次不受限制的 FLOAT 和 NUMBER 显示相同的值,而受限制的 FLOAT 具有您期望的精度。

所以它在第 40 位之后显示零,并且第 40 位是 5 而不是 4,因为您已经超出了精度并且该值被四舍五入到最高有效位。 SQL REAL 数据类型的精度为 63 位二进制或 18 位十进制数字;但除非指定 PL/SQL REAL 匹配 NUMBER。

【讨论】:

以上是关于PLSQL 中的 REAL 数据类型的主要内容,如果未能解决你的问题,请参考以下文章

float 和 real 数据类型 的区别??

float 和 real 数据类型 的区别??

关于c语言的数据类型real_T,int_T和real,int的区别

PLSQL 在变量中存储具有未知数据类型的游标(使用 FETCH INTO)

SqlServer中decimal,float 和 real 数据类型的区别

浮点、实数和小数数据类型的回顾