Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Schleppende Null

Kürzlich stellte mir ein Entwickler eine interessante Frage. Er arbeitete an einem Problem, bei dem numerische Werte in einer Tabelle gespeichert waren, aber als er diese Tabelle in PL/SQL Developer abfragte, wurden nachgestellte Nullen nach der letzten Ziffer angezeigt. Er fragte sich, ob dies zu dem Problem beitrug, das er zu debuggen versuchte. Der Entwickler musste wissen, ob Oracle diese nachgestellten Nullen gespeichert hat.

Meine Antwort war, dass Oracle keine abschließenden Nullen speichert. Oracle speichert nur den Exponenten und die Mantisse der Zahl. Oracle füllt den numerischen Wert nicht rechts mit Nullen auf. Der Entwickler wusste nun, dass sein Problem nicht mit den Daten in der Datenbank, sondern mit etwas zu tun hatte, was seine Entwicklungsplattform tat.

Aber stimmte meine Aussage? Ich habe oft eine Aussage darüber gemacht, wie Oracle intern funktioniert, musste dann aber zurückgehen und meine Aussage validieren oder beweisen, dass sie falsch war, was unweigerlich zur richtigen Aussage führt.

Um meine Aussage zu testen, habe ich eine einfache Tabelle erstellt und Daten darin eingefügt.

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

In SQL*Plus sehen wir keine abschließenden Nullen, obwohl ich sie explizit eingefügt habe. Die Werte 25 und 25.0 sowie 25.2 und 25.20 sehen alle gleich aus. Aber vielleicht zeigt SQL*Plus die Werte einfach so an. Lassen Sie uns also den Datenblock ausgeben, um zu sehen, wie genau Oracle diese Werte speichert.

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.

Ich musste die Datei- und Blocknummer für mein von mir erstelltes Segment ermitteln. Ich habe dann den Befehl ausgegeben, den Inhalt der Datenblöcke in eine Ablaufverfolgungsdatei zu kopieren. Wenn Sie in der Ablaufverfolgungsdatei nach dem Schlüsselwort „block_row_dump“ suchen, können Sie den Inhalt dieser Zeilen im folgenden Dump sehen:

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

Aus dem Blockdump können wir ersehen, dass der erste Wert 2 Byte lang ist und aus den Hex-Zeichen „C1 1A“ besteht. Die zweite Reihe hat die gleichen genauen Werte! Dies ist wichtig, da es meine anfängliche Behauptung bestätigt, dass Oracle keine zusätzlichen Nullen für die zweite Zeile in der Tabelle speichert. Wenn es eine zusätzliche Null gäbe, wäre die Länge nicht 2 Byte. Für die dritte und vierte Zeile sehen wir, dass die Hex-Werte identisch sind, „C1 1A 15“.

Aber seien wir sicher, dass diese Hex-Werte unseren Daten entsprechen. Dazu verwenden wir die DBMS_STATS.CONVERT_RAW_VALUE-Prozedur.

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.

Die Hex-Werte „C1 1A“ sind also die interne (rohe) Darstellung von „25“ und „C1 1A 15“ ist 25,2, wie wir es erwartet hätten.

Die Moral dieser Geschichte ist, dass Sie manchmal, wenn Sie glauben zu wissen, wie Oracle intern arbeitet, möglicherweise noch einen Testfall entwickeln müssen, um Ihre Aussagen zu validieren.