sql >> Databáze >  >> RDS >> Oracle

Trailing Zero

Nedávno mi jeden vývojář položil zajímavou otázku. Pracoval na problému, kdy byly číselné hodnoty uloženy v tabulce, ale když se na tuto tabulku zeptal v PL/SQL Developer, za poslední číslicí se zobrazily koncové nuly. Uvažoval, jestli to nepřispívá k problému, který se snažil odladit. Vývojář potřeboval vědět, zda Oracle ukládá tyto koncové nuly.

Moje odpověď byla, že Oracle neukládá koncové nuly. Oracle ukládá pouze exponent a mantisu čísla. Oracle nevyplňuje číselnou hodnotu vpravo nulami. Vývojář nyní věděl, že jeho problém není s daty v databázi, ale spíše s něčím, co dělá jeho vývojová platforma.

Ale byl můj výrok pravdivý? Mnohokrát jsem učinil prohlášení o tom, jak Oracle interně funguje, ale pak jsem se musel vrátit a potvrdit své prohlášení nebo prokázat, že bylo nepravdivé, což nevyhnutelně vede ke správnému prohlášení.

Abych své tvrzení otestoval, vytvořil jsem jednoduchou tabulku a vložil do ní data.

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

V SQL*Plus nevidíme žádné koncové nuly, i když jsem je explicitně přidal. Hodnoty 25 a 25,0 a také 25,2 a 25,20 vypadají všechny stejně. Ale možná je to jen způsob, jakým SQL*Plus zobrazuje hodnoty. Pojďme tedy vypsat datový blok, abychom viděli, jak přesně Oracle tyto hodnoty ukládá.

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.

Musel jsem určit soubor a číslo bloku pro svůj segment, který jsem vytvořil. Poté jsem vydal příkaz k výpisu obsahu datových bloků do trasovacího souboru. Když se podíváte do trasovacího souboru, vyhledejte klíčové slovo „block_row_dump“ a níže uvidíte obsah těchto řádků ve výpisu:

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

Z výpisu bloku vidíme, že první hodnota je dlouhá 2 bajty a skládá se z hexadecimálních znaků „C1 1A“. Druhý řádek má stejné přesné hodnoty! To je důležité, protože to potvrzuje mé původní tvrzení, že Oracle neukládá žádné nuly navíc pro druhý řádek v tabulce. Pokud by tam byla nula navíc, délka by nebyla 2 bajty. U třetího a čtvrtého řádku vidíme, že hexadecimální hodnoty jsou identické, „C1 1A 15“.

Ale buďme si jisti, že tyto hexadecimální hodnoty odpovídají našim datům. K tomu použijeme postup 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.

Hexadecimální hodnoty „C1 1A“ jsou tedy vnitřní (nezpracované) vyjádření „25“ a „C1 1A 15“ je 25,2, jak bychom očekávali.

Morálka tohoto příběhu spočívá v tom, že někdy, když si myslíte, že víte, jak Oracle interně funguje, možná budete muset vymyslet testovací případ pro ověření vašich prohlášení.


  1. Co potřebuji ke spuštění SQL?

  2. Konfigurace PostgreSQL pro kontinuitu podnikání

  3. Monitorování SQL databáze přes SP_WhoIsActive nebo FogLight | Řešení problémů s výkonem serveru SQL -1

  4. Operátor SQL se rovná (=) pro začátečníky