Як працюють значення 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.