Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Końcowe zero

Niedawno programista zadał mi ciekawe pytanie. Pracował nad problemem, w którym wartości liczbowe były przechowywane w tabeli, ale gdy odpytywał tę tabelę w PL/SQL Developer, wyświetlała ona końcowe zera po ostatniej cyfrze. Zastanawiał się, czy to przyczyniło się do problemu, który próbował debugować. Deweloper musiał wiedzieć, czy Oracle przechowuje te końcowe zera.

Moja odpowiedź była taka, że ​​Oracle nie przechowuje końcowych zer. Oracle przechowuje tylko wykładnik i mantysę liczby. Oracle nie dopełnia wartości numerycznej zerami z prawej strony. Deweloper wiedział teraz, że jego problem nie dotyczył danych w bazie danych, ale raczej czegoś, co robiła jego platforma programistyczna.

Ale czy moje stwierdzenie było prawdziwe? Wiele razy składałem oświadczenie o tym, jak Oracle działa wewnętrznie, ale potem musiałem wrócić i zweryfikować moje oświadczenie lub udowodnić, że jest fałszywe, co nieuchronnie prowadzi do prawidłowego stwierdzenia.

Aby przetestować moje oświadczenie, utworzyłem prostą tabelę i wstawiłem do niej dane.

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

W SQL*Plus nie widzimy żadnych końcowych zer, mimo że wyraźnie je dodałem. Wartości 25 i 25.0 oraz 25.2 i 25.20 wyglądają tak samo. Ale może właśnie tak SQL*Plus wyświetla wartości. Zrzućmy więc blok danych, aby zobaczyć, jak dokładnie Oracle przechowuje te wartości.

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.

Musiałem określić plik i numer bloku dla utworzonego przeze mnie segmentu. Następnie wydałem polecenie zrzucenia zawartości bloków danych do pliku śledzenia. Kiedy zajrzysz do pliku śledzenia, wyszukaj słowo kluczowe „block_row_dump”, a poniżej zobaczysz zawartość tych wierszy w zrzucie:

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

Widzimy ze zrzutu bloku, że pierwsza wartość ma długość 2 bajtów i składa się ze znaków szesnastkowych „C1 1A”. Drugi rząd ma dokładnie te same wartości! Jest to ważne, ponieważ weryfikuje moje początkowe twierdzenie, że Oracle nie przechowuje żadnych dodatkowych zer w drugim wierszu tabeli. Gdyby było dodatkowe zero, długość nie wynosiłaby 2 bajtów. W trzecim i czwartym rzędzie widzimy, że wartości szesnastkowe są identyczne, „C1 1A 15”.

Ale bądźmy pewni, że te wartości szesnastkowe odpowiadają naszym danym. W tym celu użyjemy procedury 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.

Tak więc wartości szesnastkowe „C1 1A” są wewnętrzną (surową) reprezentacją „25”, a „C1 1A 15” to 25,2 zgodnie z naszymi oczekiwaniami.

Morał z tej historii jest taki, że czasami, gdy wydaje Ci się, że wiesz, jak działa Oracle wewnętrznie, nadal będziesz musiał opracować przypadek testowy, aby zweryfikować swoje oświadczenia.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Analiza ciśnienia pamięci Stan ryzyka

  2. Jaki jest limit rozmiaru argumentu podprogramu varchar2 PL/SQL w Oracle?

  3. SQL Join na wartościach null

  4. Doradca ds. kompresji 11gR2 =Zło

  5. Jak sprawdzić nieaktualne statystyki