Oracle
 sql >> база данни >  >> RDS >> Oracle

Следваща нула

Наскоро накарах разработчик да ми зададе интересен въпрос. Той работеше върху проблем, при който числовите стойности бяха съхранени в таблица, но когато поиска тази таблица в PL/SQL Developer, тя щеше да покаже крайни нули след последната цифра. Той се чудеше дали това допринася за проблема, който се опитваше да отстрани. Разработчикът трябваше да знае дали Oracle съхранява тези последващи нули.

Моят отговор беше, че Oracle не съхранява последващи нули. Oracle съхранява само степента и мантисата на числото. Oracle не поставя вдясно числовата стойност с нули. Разработчикът вече знаеше, че проблемът му не е в данните в базата данни, а по-скоро в нещо, което неговата платформа за разработка прави.

Но вярно ли беше моето твърдение? Много пъти съм правил изявление за това как Oracle работи вътрешно, но след това трябваше да се върна и да потвърдя твърдението си или да докажа, че е невярно, което неизбежно води до правилното твърдение.

За да тествам изявлението си, създадох проста таблица и вмъкнах данни в нея.

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

В SQL*Plus не виждаме никакви нули в края, въпреки че ги добавих изрично. Стойностите 25 и 25.0, както и 25.2 и 25.20 изглеждат еднакви. Но може би точно така SQL*Plus показва стойностите. Така че нека изхвърлим блока от данни, за да видим как точно Oracle съхранява тези стойности.

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.

Трябваше да определя номера на файла и блока за моя сегмент, който създадох. След това издадох командата за изхвърляне на съдържанието на блоковете данни във файл за проследяване. Когато погледнете файла за проследяване, потърсете ключовата дума „block_row_dump“ и можете да видите съдържанието на тези редове в dump по-долу:

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

От дъмпа на блока можем да видим, че първата стойност е дълга 2 байта и се състои от шестнадесетичните символи „C1 1A“. Вторият ред има същите точни стойности! Това е важно, защото потвърждава първоначалното ми твърдение, че Oracle не съхранява никакви допълнителни нули за втория ред в таблицата. Ако имаше допълнителна нула, дължината нямаше да е 2 байта. За третия и четвъртия ред можем да видим, че шестнадесетичните стойности са идентични, „C1 1A 15“.

Но нека бъдем сигурни, че тези шестнадесетични стойности съответстват на нашите данни. За да направим това, ще използваме процедурата 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.

Така че шестнадесетичните стойности „C1 1A“ са вътрешното (необработено) представяне на „25“, а „C1 1A 15“ е 25,2, както бихме очаквали.

Моралът на тази история е, че понякога, когато си мислите, че знаете как Oracle работи вътрешно, може да се наложи да измислите тестов случай, за да потвърдите твърденията си.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да използвам ключовата дума 'as' за псевдоним на таблица в Oracle?

  2. как да Flashback, когато имаме защита на данните

  3. Как да промените таблицата за добавяне на колона оракул

  4. Как мога да дам псевдоним на таблица в Oracle?

  5. Кога трябва да използвам точка и запетая срещу наклонена черта в Oracle SQL?