Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

Oracle SQL Date to Long dan sebaliknya

Anda kehilangan terlalu banyak presisi dalam konversi Anda untuk dapat kembali ke arah lain. Anda bisa lebih dekat dengan menggunakan stempel waktu alih-alih tanggal.

Pertama, kueri awal Anda kehilangan komponen waktu sepenuhnya:

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

... tetapi bahkan dengan itu, mengubah kembali telah kehilangan terlalu banyak:

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

Mana yang lebih dekat dari 1432549301782839296 yang Anda dapatkan, tapi masih jauh.

Sebagian dari masalahnya adalah ketepatan DATE , yang hanya untuk yang kedua. Jika Anda menggunakan TIMESTAMP sebaliknya Anda bisa cukup dekat; Anda dapat melihat bahwa nilai yang dimiliki seharusnya sangat tepat:

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

Mengonversi kembali itu diperumit oleh aritmatika stempel waktu yang memberikan hasil interval, yang kemudian harus Anda manipulasi untuk kembali ke angka, pertama sebagai jumlah hari asli:

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

... dan kemudian dengan manipulasi kekuatan Anda:

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

Yang sangat sangat dekat. Anda dapat memotong atau membulatkannya ke bilangan bulat terdekat.

Hanya dengan melihat angka-angka Anda dan manipulasi kekuatan setiap cara menunjukkan bahwa itu tampaknya berada dalam ketepatan yang dapat diatasi 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...

Bahkan dengan stempel waktu, Anda kehilangan sebagian dari itu, karena nilai pertama melewati batas pecahan 9 digit kedua. Bagian yang mewakili pecahan detik - setelah Anda menghitung 15895 jam, dll. - adalah .0000089776673785814232865555418862 hari, yaitu .77567046150943497195839881896768 detik; stempel waktu membulatkannya menjadi .775670462 . Jadi tidak akan pernah sempurna.

Itu juga membuat orang bertanya-tanya bagaimana nomor asli dihasilkan; sepertinya tidak mungkin itu benar-benar mewakili waktu hingga presisi ekstrem itu, karena di bawah yoctoseconds . Tidak terlalu jelas apakah 'presisi' sebenarnya adalah artefak yang dimanipulasi berdasarkan kekuatan 2, tetapi tetap tidak terlihat sangat berguna. Lebih umum menggunakan tanggal epoch gaya Unix, menghitung detik atau terkadang milidetik sejak tanggal epoch yang Anda gunakan, jika harus disimpan sebagai angka sama sekali. Desain ini... menarik.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tautkan Kembali Infrastruktur Jaringan

  2. 3 Cara Mengembalikan Zona Waktu dari Nilai Datetime di Oracle

  3. <SQL>Cara mengubah ukuran VARCHAR2 tabel

  4. Tidak dapat membuat Oracle View mengakses objek skema lain, meskipun ada hibah

  5. SQL IN Klausul 1000 batas item