Як працюють значення DATETIME в SQLite?


110

Я створюю програми для Android, і мені потрібно зберегти дату / час запису про створення. Документи SQLite, однак, кажуть, що "SQLite не має класу зберігання, відведеного для зберігання дат та / або разів", і він "здатний зберігати дати та часи як значення TEXT, REAL або INTEGER".

Чи є технічні причини використовувати один тип над іншим? І чи може одна колонка зберігати дати в будь-якому з трьох форматів від рядка до рядка?

Мені потрібно буде порівняти дати пізніше. Наприклад, у своїх додатках я покажу всі записи, створені між датою A до датою B. Я переживаю, що відсутність справжнього стовпця DATETIME може ускладнити порівняння.


Відповіді:


83

SQlite не має конкретного типу часу. Ви можете використовувати TEXT, REALабо INTEGERтип, в залежності від того відповідає вашим потребам.

Прямо від DOCS

У SQLite немає класу зберігання, відведеного для зберігання дат та / або разів. Натомість вбудовані функції дати та часу SQLite здатні зберігати дати та часи як значення TEXT, REAL або INTEGER:

  • ТЕКСТ у вигляді рядків ISO8601 ("РРРР-ММ-DD HH: MM: SS.SSS").
  • РЕАЛЬНІ як номери Джуліана, кількість днів з полудня в Ґрінвічі 24 листопада 4714 р. До н.е. згідно з пролептичним григоріанським календарем.
  • INTEGER як Unix Time, кількість секунд з 1970-01-01 00:00:00 UTC.

Програми можуть вибирати дати та час у будь-якому з цих форматів та вільно конвертувати між форматами, використовуючи вбудовані функції дати та часу.

Тут можна знайти вбудовані функції дати та часу SQLite .


11
Важливо зауважити - усі методи зберігання дат використовують формати, які можна порівняти, використовуючи оператори стандарт =, <,> та BETWEEN.
Ларрі Люстіг

2
"У SQLite немає класу зберігання, призначеного для зберігання дат та / або часів" - за винятком типів ДАТА та ДАТЕТИМЕ, які ніколи не згадуються в документації
Слабко

12
@Slabko Це не так. SQLite дозволяє що-небудь (включаючи DATETIME) як оголошений тип стовпця. Виходячи з цього, він надає цьому стовпцю спорідненість із класом зберігання (він навіть має приклад того, як це працює для DATETIME в документації). Ця спорідненість більше нагадує підказку, оскільки кожен запис стовпця може насправді мати різний клас зберігання. Клас зберігання все ще на крок слабший за тип і може бути підкріплений кількома типами. Так що так, ви можете використовувати DATETIME. Ні, він насправді не підтримує його як тип або клас зберігання. Так, документація насправді містить слово "ДАТЕТИМ".
Джаспер

20

У SQLite немає класу зберігання, відведеного для зберігання дат та / або разів. Натомість вбудовані функції дати та часу SQLite здатні зберігати дати та часи як значення TEXT, REAL або INTEGER:

ТЕКСТ у вигляді рядків ISO8601 ("РРРР-ММ-DD HH: MM: SS.SSS"). РЕАЛЬНІ як номери Джуліана, кількість днів з полудня в Ґрінвічі 24 листопада 4714 р. До н.е. згідно з пролептичним григоріанським календарем. INTEGER як Unix Time, кількість секунд з 1970-01-01 00:00:00 UTC. Програми можуть вибирати дати та час у будь-якому з цих форматів та вільно конвертувати між форматами, використовуючи вбудовані функції дати та часу.

Сказавши це, я би використовував INTEGER і зберігав секунди з епохи Unix (1970-01-01 00:00:00 UTC).


1
Я також вважаю за краще це. Стандартні класи, пов’язані з датою / часом, все одно підкріплені внутрішньо довгими, і порівняти довгі досить просто.
Каракурі

1
@dtmilano Чому ви віддаєте перевагу INTEGER тут, а не String?
ІгорГанапольський

1
INTEGER використовує лише 8 байт, TEXT у цьому прикладі використовує 23 байти. Це не ясно, як вибрати, в якому типі він зберігає дані. Чи означає це, що якщо я створю стовпець типу INTEGER, функції автоматично зберігатимуться як Unix Time?
rayzinnz

2
REAL також використовує 8 байт. Епохальні секунди становитимуть 10 цифр до кінця 2286 року, а оскільки подвійний IEEE підтримує 15-17 значущих цифр , це дає вам кращу роздільну здатність в мілісекундах. RSQLiteначебто перетворюється POSIXctна числову епоху, тому для мене це працює досить добре.
r2evans

@ r2evans Я не впевнений, що ти кажеш. Якщо я хочу зберігати мілісекунди з епохи, як це зробити?
Майкл

14

Одна з потужних особливостей SQLite дозволяє вибирати тип зберігання. Переваги / недоліки кожного з трьох різних можливостей:

  • Рядок ISO8601

    • Порівняння рядків дає дійсні результати
    • Зберігає дріб секунди, до трьох десяткових цифр
    • Потрібно більше місця для зберігання
    • Його значення ви побачите безпосередньо під час використання браузера бази даних
    • Необхідність розбору для інших цілей
    • Модифікатор стовпців "current_timestamp" за замовчуванням зберігатиметься у цьому форматі
  • Реальне число

    • Висока точність відносно дрібних секунд
    • Найдовший діапазон часу
  • Цілий номер

    • Найнижчий простір для зберігання
    • Швидкі операції
    • Невеликий часовий діапазон
    • Можлива проблема 2038 року

Якщо вам потрібно порівняти різні типи або експортувати до зовнішньої програми, ви можете скористатись функціями перетворення власних функцій SQLite за необхідності.


1
Чому виникає проблема 2038 року? Здається, INTEGER підтримує 64-бітове зберігання.
guan boshen

1
@guanboshen Наскільки я можу сказати, єдиною причиною турбуватися з приводу 2038 року буде підтримка хост-платформи. Документація на SQLite вимагає використання C localtime_r()( sqlite.org/lang_datefunc.html#caveats_and_bugs ) у еталонній реалізації та localtime()може бути вразливою до 2038 року, якщо хост-платформа має 32-бітну версію time_t. Зважаючи на це, оскільки SQLite претендує на захист від такої можливості шляхом відображення зовнішніх дат у безпечне попереднє перетворення діапазону (див. Те саме посилання), я думаю, це навряд чи буде проблемою, за винятком, можливо, езотеричних випадків.
Зоя Спаркс

@ ZoëSparks Дякую за роз’яснення.
guan boshen

7

Практично всі питання, що стосуються дати та часу, я вважаю за краще спростити речі, дуже-дуже прості ... До секунд, збережених у цілих числах.

Цілі особи завжди будуть підтримуватися у вигляді цілих чисел у базах даних, плоских файлах тощо. Ви трохи піддаєте математиці та переносите їх на інший тип, і ви можете відформатувати дату в будь-якому випадку.

Роблячи це таким чином, вам не доведеться хвилюватися, коли [вставити поточну улюблену базу даних тут] замінено на [майбутня улюблена база даних], яка випадково не використовувала формат дати, який ви вибрали сьогодні.

Це лише невеликі накладні витрати на математику (наприклад, методи - це займає дві секунди, я при необхідності відправлю суть) і спрощує речі для багатьох операцій щодо дати / часу пізніше.


7

Зберігайте його в полі типу long. Дивіться Date.getTime()іnew Date(long)


як я можу порівняти його ?? Ви можете дати мені зразок запиту ..: D
Хаїріл Ушан

Подивіться на Joda Time для порівнянь у коді ( joda-time.sourceforge.net ) та використовуйте просте довге порівняння в SQL (наприклад, порівняння чисел).
Синтаксис

виберіть * з таблиці, де створюється між a і b;
koem
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.