Добре, обикновено не отговарям на собствените си въпроси, но след малко бърникане разбрах окончателно как Oracle съхранява резултата от изваждане на ДАТА.
Когато извадите 2 дати, стойността не е тип данни NUMBER (както би ви накарало да повярвате в справочното ръководство на Oracle 11.2 SQL). Номерът на вътрешния тип данни на изваждане DATE е 14, което е недокументиран вътрешен тип данни (NUMBER е вътрешен тип данни номер 2). Въпреки това, той всъщност се съхранява като 2 отделни допълващи се числа със знак от две, като първите 4 байта се използват за представяне на броя дни, а последните 4 байта, използвани за представяне на броя на секундите.
Пример за изваждане на DATE, което води до положителна разлика в цяло число:
select date '2009-08-07' - date '2008-08-08' from dual;
Резултати в:
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
Припомнете си, че резултатът е представен като 2 отделни две допълнения със знак от 4 байтови числа. Тъй като в този случай няма десетични знаци (точно 364 дни и 0 часа), последните 4 байта са 0 и могат да бъдат игнорирани. За първите 4 байта, тъй като моят процесор има архитектура с малък ендиан, байтовете са обърнати и трябва да се четат като 1108 или 0x16c, което е десетично 364.
Пример за изваждане на DATE, което води до отрицателна целочислена разлика:
select date '1000-08-07' - date '2008-08-08' from dual;
Резултати в:
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
Отново, тъй като използвам машина с малък ендиан, байтовете са обърнати и трябва да се четат като 255,250,97,224, което съответства на 11111111 11111010 01100001 11011111. Сега, тъй като това е в допълнение към две, знаем, че числото enco bin е със знак отрицателно, защото най-лявата двоична цифра е 1. За да преобразуваме това в десетично число, ще трябва да обърнем допълнението на 2 (изваждаме 1 и след това правим допълнението на единицата), което води до:00000000 00000101 10011110 00100006810, което е равно. P>
Пример за изваждане на DATE, което води до десетична разлика:
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
Разликата между тези 2 дати е 0,25 дни или 6 часа.
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
Сега този път, тъй като разликата е 0 дни и 6 часа, се очаква първите 4 байта да са 0. За последните 4 байта можем да ги обърнем (тъй като CPU е с малък байт) и да получим 84,96 =01010100 01100000 основа 2 =21600 в десетичната запетая. Преобразуването на 21600 секунди в часове ви дава 6 часа, което е разликата, която очаквахме.
Надявам се това да помогне на всеки, който се чудеше как всъщност се съхранява изваждане на ДАТА.