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

Odejmowanie dat w Oracle — liczba czy typ danych przedziału?

Ok, zwykle nie odpowiadam na własne pytania, ale po odrobinie majsterkowania ostatecznie odkryłem, w jaki sposób Oracle przechowuje wynik odejmowania DATY.

Po odjęciu 2 dat wartość nie jest typem danych LICZBA (jak sugeruje podręcznik Oracle 11.2 SQL Reference). Wewnętrzny numer typu danych odejmowania DATE to 14, co jest nieudokumentowanym wewnętrznym typem danych (NUMBER to wewnętrzny typ danych numer 2). Jednak w rzeczywistości jest przechowywany jako 2 oddzielne liczby ze znakiem uzupełnienia do dwóch, przy czym pierwsze 4 bajty służą do reprezentowania liczby dni, a ostatnie 4 bajty do reprezentowania liczby sekund.

Przykład odejmowania DATE dającego dodatnią różnicę między liczbami całkowitymi:

select date '2009-08-07' - date '2008-08-08' from dual;

Wyniki w:

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

Przypomnijmy, że wynik jest reprezentowany jako dopełnienie do dwóch oddzielnych dwójek ze znakiem 4 bajtów. Ponieważ w tym przypadku nie ma miejsc dziesiętnych (dokładnie 364 dni i 0 godzin), ostatnie 4 bajty są zerami i można je zignorować. W przypadku pierwszych 4 bajtów, ponieważ mój procesor ma architekturę little-endian, bajty są odwrócone i powinny być odczytywane jako 1,108 lub 0x16c, co jest liczbą dziesiętną 364.

Przykład odejmowania DATE skutkującego ujemną różnicą między liczbami całkowitymi:

select date '1000-08-07' - date '2008-08-08' from dual;

Wyniki w:

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

Ponownie, ponieważ używam maszyny little-endian, bajty są odwrócone i powinny być odczytywane jako 255 250 97 224, co odpowiada 11111111 11111010 01100001 11011111. Teraz, ponieważ jest to kodowanie binarne ze znakiem uzupełnienia do dwóch, wiemy, że liczba to ujemna, ponieważ ostatnia cyfra dwójkowa po lewej stronie to 1. Aby przekonwertować to na liczbę dziesiętną, musielibyśmy odwrócić uzupełnienie do dwójek (odjąć 1, a następnie wykonać uzupełnienie do jedynki), co da wynik:00000000 00000101 10011110 00100000, co daje -368160 zgodnie z podejrzeniami.

Przykład odejmowania DATY w wyniku różnicy dziesiętnej:

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

Różnica między tymi 2 datami wynosi 0,25 dnia lub 6 godzin.

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

Teraz tym razem, ponieważ różnica wynosi 0 dni i 6 godzin, oczekuje się, że pierwsze 4 bajty to 0. Dla ostatnich 4 bajtów możemy je odwrócić (ponieważ procesor jest little-endian) i uzyskać 84,96 =01010100 0110000 podstawa 2 =21600 dziesiętnie. Konwersja 21600 sekund na godziny daje 6 godzin, co jest oczekiwaną różnicą.

Mam nadzieję, że pomoże to każdemu, kto zastanawiał się, jak faktycznie przechowywane jest odejmowanie DATY.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Aktualizacja krytycznej poprawki Oracle — październik 2020 r.

  2. ROWIDTOCHAR() Funkcja w Oracle

  3. Wydajność SUBSTR na CLOB

  4. Wdrażaj wiele instancji obliczeniowych Oracle przy użyciu puli instancji i terraform

  5. Ślad SQL, zdarzenie 10046 w Oracle:trcsess, narzędzie tkprof