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

Oracle SQL Date to Long i na odwrót

Tracisz zbyt dużo precyzji w konwersji, aby móc cofnąć się w drugą stronę. Możesz się zbliżyć, używając znaczników czasu zamiast dat.

Po pierwsze, początkowe zapytanie całkowicie straciło składnik czasu:

select to_char(date '1970-01-01'
  + (1432550197431912935 - power(2, 60))/power(2, 44), 'YYYY-MM-DD HH24:MI:SS')
from dual;

2013-07-09 01:13:19

... ale nawet przy tym konwersja powrotna straciła zbyt wiele:

select ((to_date('2013-07-09 01:13:19','YYYY-MM-DD HH24:MI:SS')
  - date '1970-01-01') * power(2, 44)) + power(2, 60) from dual;

1432550197477589405

Co jest bliżej niż 1432549301782839296, które masz, ale wciąż dość daleko.

Częścią problemu jest precyzja DATE , który jest tylko do drugiego. Jeśli używasz TIMESTAMP zamiast tego możesz podejść całkiem blisko; widać, że wartość, którą należy mieć, jest podobno bardzo precyzyjna:

select timestamp '1970-01-01 00:00:00'
  + numtodsinterval((1432550197431912935 - power(2, 60))/power(2, 44), 'DAY')
from dual;

2013-07-09 01:13:18.775670462

Konwersja tego wstecz jest skomplikowana przez arytmetykę znacznika czasu dającą wyniki interwału, które następnie trzeba manipulować, aby powrócić do liczby, najpierw jako oryginalnej liczby dni:

select extract(day from int_val)
  + extract(hour from int_val) / 24
  + extract(minute from int_val) / (24 * 60)
  + extract(second from int_val) / (24 * 60 * 60)
from (
select to_timestamp('2013-07-09 01.13.18.775670462', 'YYYY-MM-DD HH24:MI:SS.FF9')
  - timestamp '1970-01-01 00:00:00' as int_val from dual);

15895.0509117554451620370370370370370371

... a potem z manipulacją mocą:

select ((extract(day from int_val)
    + extract(hour from int_val) / 24
    + extract(minute from int_val) / (24 * 60)
    + extract(second from int_val) / (24 * 60 * 60))
  * power(2, 44)) + power(2, 60)
as x
from (
select to_timestamp('2013-07-09 01.13.18.775670462', 'YYYY-MM-DD HH24:MI:SS.FF9')
  - timestamp '1970-01-01 00:00:00' as int_val from dual);

1432550197431912935.09988554676148148148

Co jest cholernie bliskie. Możesz to skrócić lub zaokrąglić do najbliższej liczby całkowitej.

Wystarczy spojrzeć na swoje liczby i manipulację mocą w każdą stronę, aby pokazać, że wydaje się, że mieści się to w precyzji, z jaką może sobie poradzić Oracle:

select (1432550197431912935 - power(2, 60)) / power(2, 44)
from dual;

15895.050911755445156359201064333319664

select (15895.050911755445156359201064333319664 * power(2, 44)) + power(2, 60)
from dual;

1432550197431912935.000...

Nawet ze znacznikiem czasu tracisz część tego, ponieważ ta pierwsza wartość przekracza 9-cyfrowy limit drugiego ułamka. Część reprezentująca ułamki sekund — po uwzględnieniu 15895 godzin itd. — to .0000089776673785814232865555418862 dnia, czyli .77567046150943497195839881896768 sekundy; znacznik czasu zaokrągla to do .775670462 . Więc nigdy nie będzie idealnie.

To również prowadzi do zastanowienia się, w jaki sposób generowana jest oryginalna liczba; wydaje się mało prawdopodobne, że w rzeczywistości reprezentuje czas do tej ekstremalnej precyzji, ponieważ wynosi on poniżej joktosekund . Nie jest jasne, czy „precyzja” jest w rzeczywistości artefaktem manipulacji w oparciu o moc 2, ale i tak nie wygląda to zbyt użytecznie. Częściej używa się daty epoki w stylu Uniksa, licząc sekundy, a czasem milisekundy od daty epoki, której i tak używasz, jeśli w ogóle ma być przechowywana jako liczba. Ten projekt jest... interesujący.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Oracle.ManagedDataAccess nie rozpoznaje aliasu w parametrach połączenia

  2. ORA-01704:literał ciągu za długi „Błąd podczas wstawiania dokumentu XML w kolumnie typu Oracle XMLTYPE”

  3. Problem polegający na tym, że zmienne wiążące Oracle nie używają poprawnie indeksu

  4. Jak używać %ROWTYPE podczas wstawiania do tabeli Oracle z kolumną tożsamości?

  5. Wyjątek Java Oracle - maksymalna liczba wyrażeń na liście to 1000