DATETIME değerleri SQLite'da nasıl çalışır?


110

Android uygulamaları oluşturuyorum ve oluşturma kaydının tarihini / saatini kaydetmem gerekiyor. Bununla birlikte, SQLite belgeleri, "SQLite, tarihleri ​​ve / veya saatleri depolamak için ayrılmış bir depolama sınıfına sahip değildir" ve "tarihleri ​​ve saatleri METİN, GERÇEK veya TAMAMLAYICI değerleri olarak depolayabilir" diyor.

Bir türü diğerine tercih etmenin teknik bir nedeni var mı? Ve tek bir sütun tarihleri, satırdan satıra üç biçimden herhangi birinde depolayabilir mi?

Tarihleri ​​daha sonra karşılaştırmam gerekecek. Örneğin, uygulamalarımda A tarihinden B tarihine kadar oluşturulan tüm kayıtları göstereceğim. Gerçek bir DATETIME sütunu olmamasının karşılaştırmaları zorlaştıracağından endişeliyim.


Yanıtlar:


83

SQlite belirli bir tarih saat türüne sahip değildir. Sen kullanabilirsiniz TEXT, REALya INTEGERda uygun olanı türleri.

Doğrudan DOCS'tan

SQLite, tarihleri ​​ve / veya saatleri depolamak için ayrılmış bir depolama sınıfına sahip değildir. Bunun yerine, SQLite'nin yerleşik Tarih ve Saat İşlevleri, tarihleri ​​ve saatleri TEXT, REAL veya INTEGER değerleri olarak depolayabilir:

  • ISO8601 dizeleri olarak METİN ("YYYY-AA-GG SS: DD: SS.SSS").
  • Jülyen günü sayıları olarak GERÇEK, proleptik Gregoryen takvimine göre MÖ 24 Kasım 4714'te Greenwich'te öğleden bu yana geçen günlerin sayısı.
  • INTEGER Unix Time olarak, 1970-01-01 00:00:00 UTC'den bu yana geçen saniye sayısı.

Uygulamalar, tarihleri ​​ve saatleri bu biçimlerden herhangi birinde depolamayı seçebilir ve yerleşik tarih ve saat işlevlerini kullanarak biçimler arasında serbestçe dönüştürme yapabilir.

SQLite yerleşik Tarih ve Saat işlevleri burada bulunabilir .


11
Unutulmaması gereken önemli - tarihleri ​​saklamanın tüm yöntemleri, standart =, <,> ve BETWEEN operatörleri kullanılarak karşılaştırılabilen formatlar kullanır.
Larry Lustig

2
"SQLite, tarihleri ​​ve / veya saatleri depolamak için ayrılmış bir depolama sınıfına sahip değil" - dokümantasyonda hiç belirtilmeyen DATE ve DATETIME türlerine sahip olması dışında
Slabko

12
@Slabko Değil. SQLite, bildirilen sütun türü olarak her şeye (DATETIME dahil) izin verir. Buna dayanarak, bu sütuna bir depolama sınıfıyla bir yakınlık verir (bunun belgelerde DATETIME için nasıl çalıştığına dair bir örnek bile vardır). Bu yakınlık daha çok bir ipucu gibidir, çünkü her bir giriş sütun aslında farklı bir depolama sınıfına sahip olabilir. Bir depolama sınıfı, bir türden hala bir adım daha zayıftır ve birden çok türle desteklenebilir. Yani evet, DATETIME kullanabilirsiniz. Hayır, aslında onu bir tür veya depolama sınıfı olarak desteklemiyor. Evet, dokümantasyon aslında "DATETIME" kelimesini içeriyor.
Jasper

20

SQLite, tarihleri ​​ve / veya saatleri depolamak için ayrılmış bir depolama sınıfına sahip değildir. Bunun yerine, SQLite'nin yerleşik Tarih ve Saat İşlevleri, tarihleri ​​ve saatleri TEXT, REAL veya INTEGER değerleri olarak depolayabilir:

ISO8601 dizeleri olarak METİN ("YYYY-AA-GG SS: DD: SS.SSS"). Jülyen günü sayıları olarak GERÇEK, proleptik Gregoryen takvimine göre MÖ 24 Kasım 4714'te Greenwich'te öğleden bu yana geçen günlerin sayısı. INTEGER Unix Time olarak, 1970-01-01 00:00:00 UTC'den bu yana geçen saniye sayısı. Uygulamalar, tarihleri ​​ve saatleri bu biçimlerden herhangi birinde depolamayı seçebilir ve yerleşik tarih ve saat işlevlerini kullanarak biçimler arasında serbestçe dönüştürme yapabilir.

Bunu söyledikten sonra, INTEGER kullanacağım ve Unix döneminden (1970-01-01 00:00:00 UTC) bu yana saniyeleri saklayacaktım.


1
Ben de bunu tercih ederim. Standart tarih / saat ile ilgili sınıflar dahili olarak uzunlarla desteklenir ve uzunları karşılaştırmak oldukça kolaydır.
Karakuri

1
@dtmilano Neden burada bir String yerine INTEGER'ı tercih ediyorsunuz?
IgorGanapolsky

1
INTEGER yalnızca 8 bayt kullanır, TEXT bu örnekte 23 bayt kullanır. Verileri hangi tipte saklayacağının nasıl seçileceği açık değil. Bu, INTEGER tipinde bir sütun oluşturursam, işlevlerin otomatik olarak Unix Time olarak saklanacağı anlamına mı geliyor?
rayzinnz

2
GERÇEK de 8 bayt kullanır. Epoch saniyeleri 2286'nın sonlarına kadar 10 basamak olacak ve IEEE double 15-17 anlamlı basamağı desteklediğinden , bu size milisaniyeden daha iyi çözünürlük sağlar. sayısal bir döneme dönüşüyor RSQLitegibi görünüyor POSIXct, bu yüzden benim için yeterince iyi çalışıyor.
r2evans

@ r2evans Ne dediğinden emin değilim. Epoch'tan bu yana geçen milisaniyeleri saklamak istersem, bunu nasıl yaparım?
Michael

14

SQLite'ın güçlü özelliklerinden biri, depolama türünü seçmenize izin vermesidir. Üç farklı olasılığın her birinin avantajları / dezavantajları:

  • ISO8601 dizesi

    • Dize karşılaştırması geçerli sonuçlar verir
    • Kesir saniyelerini üç ondalık basamağa kadar depolar
    • Daha fazla depolama alanına ihtiyaç duyar
    • Bir veritabanı tarayıcısı kullanırken değerini doğrudan göreceksiniz
    • Diğer kullanımlar için ayrıştırma ihtiyacı
    • "default current_timestamp" sütun değiştiricisi bu biçimi kullanarak depolar
  • Gerçek Numara

    • Saniyelerle ilgili yüksek hassasiyet
    • En uzun zaman aralığı
  • Tam sayı

    • En düşük depolama alanı
    • Hızlı işlemler
    • Küçük zaman aralığı
    • Olası 2038 yılı sorunu

Farklı türleri karşılaştırmanız veya harici bir uygulamaya aktarmanız gerekiyorsa, gerektiğinde SQLite'ın kendi datetime dönüştürme işlevlerini kullanmakta özgürsünüz .


1
2038 sorunu neden var? INTEGER 64 bit depolamayı destekliyor gibi görünüyor.
guan boshen

1
@guanboshen Anladığım kadarıyla, 2038 için endişelenmenin tek nedeni sunucu platformunun desteği olabilir. SQLite belgeleri , referans uygulamasında C'lerilocaltime_r() ( sqlite.org/lang_datefunc.html#caveats_and_bugs ) kullandığını iddia ediyor localtime()ve ana bilgisayar platformunda 32 bit varsa potansiyel olarak 2038'e karşı savunmasız olabilir time_t. Bununla birlikte, SQLite, dış tarihleri ​​güvenli bir aralık ön dönüşümüyle eşleyerek bu olasılığa karşı koruma sağladığını iddia ettiğinden (aynı bağlantıya bakın), belki ezoterik durumlar dışında bir sorun olma ihtimalinin düşük olduğunu düşünüyorum.
Zoë Sparks

@ ZoëSparks Açıklama için teşekkür ederiz.
guan boshen

7

Neredeyse tüm tarih ve saat meseleleri için işleri basitleştirmeyi tercih ederim, çok çok basit ... Tamsayılarda saklanan saniyelere kadar.

Tamsayılar her zaman veritabanlarında, düz dosyalarda vb. Tamsayılar olarak desteklenecektir. Biraz matematik yapıp başka bir türe çeviriyorsunuz ve tarihi istediğiniz gibi biçimlendirebilirsiniz.

Bu şekilde yaptığınızda, [mevcut favori veritabanını buraya ekleyin] tesadüfen bugün seçtiğiniz tarih formatını kullanmayan [gelecekteki favori veritabanı] ile değiştirildiğinde endişelenmenize gerek kalmaz.

Bu sadece biraz matematik yüküdür (örneğin yöntemler - iki saniye sürer, gerekirse bir özet yayınlarım) ve daha sonraki tarih / saatle ilgili birçok işlem için işleri basitleştirir.


7

Bir tür alanında saklayın long. Gör Date.getTime()venew Date(long)


nasıl karşılaştırabilirim ?? bana sorgu örneğini verebilir misin ..: D
Khairil Ushan

Koddaki karşılaştırmalar için Joda Time'a bakın ( joda-time.sourceforge.net ) ve SQL'de basit uzun karşılaştırma (örneğin sayısal karşılaştırma) kullanın.
Sözdizimi

a ve b arasında oluşturulduğu tablodan * öğesini seçin;
koem
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.