Dobře, normálně na své vlastní otázky neodpovídám, ale po chvilce šťouchání jsem definitivně přišel na to, jak Oracle ukládá výsledek odečítání DATE.
Když odečtete 2 data, hodnota není datový typ NUMBER (jak byste si mysleli v referenční příručce Oracle 11.2 SQL). Číslo interního datového typu odečítání DATE je 14, což je nezdokumentovaný interní datový typ (NUMBER je interní datový typ číslo 2). Ve skutečnosti je však uložena jako 2 samostatná čísla se znaménkem se doplňkem, přičemž první 4 bajty představují počet dní a poslední 4 bajty představují počet sekund.
Příklad odčítání DATE, jehož výsledkem je kladný celočíselný rozdíl:
select date '2009-08-07' - date '2008-08-08' from dual;
Výsledky v:
DATE'2009-08-07'-DATE'2008-08-08'
---------------------------------
364
select dump(date '2009-08-07' - date '2008-08-08') from dual;
DUMP(DATE'2009-08-07'-DATE'2008
-------------------------------
Typ=14 Len=8: 108,1,0,0,0,0,0,0
Připomeňme, že výsledek je reprezentován jako 2 samostatná dvojka se znaménkem 4bytových čísel. Protože v tomto případě nejsou žádná desetinná místa (přesně 364 dní a 0 hodin), poslední 4 bajty jsou všechny 0 a lze je ignorovat. U prvních 4 bajtů, protože můj CPU má architekturu little-endian, jsou bajty obrácené a měly by se číst jako 1 108 nebo 0x16c, což je dekadicky 364.
Příklad odčítání DATE, jehož výsledkem je záporný celočíselný rozdíl:
select date '1000-08-07' - date '2008-08-08' from dual;
Výsledky v:
DATE'1000-08-07'-DATE'2008-08-08'
---------------------------------
-368160
select dump(date '1000-08-07' - date '2008-08-08') from dual;
DUMP(DATE'1000-08-07'-DATE'2008-08-0
------------------------------------
Typ=14 Len=8: 224,97,250,255,0,0,0,0
Znovu, protože používám stroj typu little-endian, bajty jsou obrácené a měly by být přečteny jako 255 250, 97 224, což odpovídá 11111111 11111010 01100001 11011111. Nyní, protože je to ve dvojkovém doplňku se znaménkem, je binární číslo záporné, protože binární číslice nejvíce vlevo je 1. Abychom toto číslo převedli na desítkové číslo, museli bychom obrátit dvojkový doplněk (odečíst 1 a poté doplnit jedničku), což má za následek:00000000 00000101 10011110 00100000, což se rovná -36816. P>
Příklad odčítání DATE, jehož výsledkem je desetinný rozdíl:
select to_date('08/AUG/2004 14:00:00', 'DD/MON/YYYY HH24:MI:SS'
- to_date('08/AUG/2004 8:00:00', 'DD/MON/YYYY HH24:MI:SS') from dual;
TO_DATE('08/AUG/200414:00:00','DD/MON/YYYYHH24:MI:SS')-TO_DATE('08/AUG/20048:00:
--------------------------------------------------------------------------------
.25
Rozdíl mezi těmito dvěma daty je 0,25 dne nebo 6 hodin.
select dump(to_date('08/AUG/2004 14:00:00', 'DD/MON/YYYY HH24:MI:SS')
- to_date('08/AUG/2004 8:00:00', 'DD/MON/YYYY HH24:MI:SS')) from dual;
DUMP(TO_DATE('08/AUG/200414:00:
-------------------------------
Typ=14 Len=8: 0,0,0,0,96,84,0,0
Tentokrát, protože rozdíl je 0 dní a 6 hodin, očekává se, že první 4 bajty jsou 0. Pro poslední 4 bajty je můžeme obrátit (protože CPU je little-endian) a dostaneme 84,96 =01010100 01100000 základ 2 =21600 v desítkové soustavě. Převedením 21600 sekund na hodiny získáte 6 hodin, což je rozdíl, který jsme očekávali.
Doufám, že to pomůže každému, kdo si kladl otázku, jak se vlastně ukládá odčítání DATE.