Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Tipo de dados REAL em PLSQL


A referência de linguagem SQL diz "O tipo de dados REAL é um número de ponto flutuante com uma precisão binária de 63 ou 18 decimal", e é mostrado como FLOAT(63). E FLUTUAR [(p)] é:

Se você criar uma tabela com uma coluna REAL, ela se comporta como um 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

Eu usei um valor menor para que ele possa ser exibido dentro do limite do SQL*Plus/SQL Developer de 49 dígitos para numformat. Observe que os valores FLOAT(126) e NUMBER não são exatamente os mesmos com esse valor.

PL/SQL é um pouco diferente. No pacote padrão você pode ver:
  type NUMBER is NUMBER_BASE;
  subtype FLOAT is NUMBER; -- NUMBER(126)
  subtype REAL is FLOAT; -- FLOAT(63)

Em um bloco PL/SQL seu REAL variável pode assumir qualquer valor que um NUMBER irrestrito pode e tem os mesmos efeitos de escala/precisão; neste caso, preservando apenas o (38- 40) dígitos e arredondando o restante para o menor desses primeiros 40 dígitos. O 'tamanho' geral do seu valor, como um número de 72 dígitos, é preservado, mas você perde a precisão além do que pode ser armazenado no formato interno do Oracle. Se você tiver os mesmos tipos de variáveis ​​do exemplo da tabela e colocar seus valores originais em:
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

Observe desta vez que o FLOAT irrestrito e NUMBER mostram o mesmo valor, enquanto os FLOATs restritos têm a precisão que você espera.

Portanto, está mostrando zeros após o 40º dígito e esse 40º dígito é 5 em vez de 4 porque você excedeu a precisão e o valor está sendo arredondado para os dígitos mais significativos. O tipo de dados SQL REAL tem precisão de 63 dígitos binários ou 18 decimais; mas, a menos que especificado, um PL/SQL REAL corresponde a NUMBER.