sql >> Base de Datos >  >> RDS >> Oracle

cero final

Un desarrollador me hizo una pregunta interesante recientemente. Estaba trabajando en un problema en el que los valores numéricos se almacenaban en una tabla, pero cuando consultaba esa tabla en PL/SQL Developer, mostraba ceros al final después del último dígito. Se preguntó si esto estaba contribuyendo al problema que estaba tratando de depurar. El desarrollador necesitaba saber si Oracle estaba almacenando esos ceros finales.

Mi respuesta fue que Oracle no almacena ceros finales. Oracle solo almacena el exponente y la mantisa del número. Oracle no rellena a la derecha el valor numérico con ceros. El desarrollador ahora sabía que su problema no era con los datos en la base de datos sino con algo que estaba haciendo su plataforma de desarrollo.

¿Pero era cierta mi afirmación? Muchas veces hice una declaración sobre cómo funciona Oracle internamente, pero luego tuve que volver y validar mi declaración o probar que era falsa, lo que inevitablemente conduce a la declaración correcta.

Para probar mi declaración, creé una tabla simple e inserté datos en ella.

SQL> create table test_tab (val number(38,5));
Table created.
SQL> insert into test_tab values (25);
1 row created.
SQL> insert into test_tab values (25.0);
1 row created.
SQL> insert into test_tab values (25.2);
1 row created.
SQL> insert into test_tab values (25.20);
1 row created.
SQL> commit;
Commit complete.
SQL> select * from test_tab;
VAL
----------
        25
        25
      25.2
      25.2

En SQL*Plus, no vemos ningún cero final aunque los agregué explícitamente. Los valores 25 y 25.0, así como 25.2 y 25.20, todos tienen el mismo aspecto. Pero tal vez así es como SQL*Plus muestra los valores. Entonces, descarguemos el bloque de datos para ver cómo Oracle almacena exactamente estos valores.

SQL> select file_id,block_id,blocks
2  from dba_extents where segment_name='TEST_TAB';
FILE_ID   BLOCK_ID     BLOCKS
---------- ---------- ----------
6        128          8
SQL> alter system dump datafile 6 block min 128 block max 135;
System altered.

Tuve que determinar el archivo y el número de bloque para mi segmento que creé. Luego emití el comando para volcar el contenido de los bloques de datos en un archivo de seguimiento. Cuando busque en el archivo de seguimiento, busque la palabra clave "block_row_dump" y podrá ver el contenido de estas filas en el volcado a continuación:

block_row_dump:
tab 0, row 0, @0x1f92
tl: 6 fb: --H-FL-- lb: 0x1  cc: 1
col  0: [ 2]  c1 1a
tab 0, row 1, @0x1f8c
tl: 6 fb: --H-FL-- lb: 0x1  cc: 1
col  0: [ 2]  c1 1a
tab 0, row 2, @0x1f85
tl: 7 fb: --H-FL-- lb: 0x1  cc: 1
col  0: [ 3]  c1 1a 15
tab 0, row 3, @0x1f7e
tl: 7 fb: --H-FL-- lb: 0x1  cc: 1
col  0: [ 3]  c1 1a 15
end_of_block_dump

Podemos ver en el volcado de bloque que el primer valor tiene una longitud de 2 bytes y consta de los caracteres hexadecimales "C1 1A". ¡La segunda fila tiene los mismos valores exactos! Esto es importante porque verifica mi afirmación inicial de que Oracle no está almacenando ceros adicionales para la segunda fila de la tabla. Si hubiera un cero adicional, la longitud no sería de 2 bytes. Para la tercera y cuarta fila, podemos ver que los valores hexadecimales son idénticos, "C1 1A 15".

Pero asegurémonos de que estos valores hexadecimales correspondan a nuestros datos. Para hacer eso, usaremos el procedimiento DBMS_STATS.CONVERT_RAW_VALUE.

SQL> set serveroutput on

SQL> declare

  2  n number;

  3  begin

  4  dbms_stats.convert_raw_value('C11A',n);

  5  dbms_output.put_line(n);

  6  end;

  7  /

25

 

PL/SQL procedure successfully completed.

 

SQL> declare

  2  n number;

  3  begin

  4  dbms_stats.convert_raw_value('C11A15',n);

  5  dbms_output.put_line(n);

  6  end;

  7  /

25.2

 

PL/SQL procedure successfully completed.

Entonces, los valores hexadecimales "C1 1A" son la representación interna (en bruto) de '25' y "C1 1A 15" es 25,2 como esperábamos.

La moraleja de esta historia es que, a veces, cuando cree que sabe cómo funciona Oracle internamente, es posible que aún tenga que idear un caso de prueba para validar sus declaraciones.