Значення часу за замовчуванням бази даних sqlite "зараз"


190

Чи можливо в базі даних sqlite створити таблицю з стовпчиком часових позначок, для якого за замовчуванням DATETIME('now')?

Подобається це:

CREATE TABLE test (
    id INTEGER PRIMARY KEY AUTOINCREMENT, 
    t TIMESTAMP DEFAULT DATETIME('now')
);

Це дає помилку ... Як вирішити?

Відповіді:


291

я вірю, що ти можеш використовувати

CREATE TABLE test (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  t TIMESTAMP
  DEFAULT CURRENT_TIMESTAMP
);

станом на версію 3.1 ( джерело )


22
Якщо вас турбує розмір пам’яті, зауважте, що цей рецепт збереже ваші часові позначки в ISO-8601 (текстовий формат), зайнявши в базі даних близько 24 байтів на дату. Ви можете заощадити простір, просто скориставшись стовпцем INTEGER (4) та зберігаючи час Unix за допомогою "INSERT INTO test (t) значень (строковий час ("% s ", CURRENT_TIME));"
mckoss

3
@mckoss завдяки вашому коментарю, заява create стала: ... mycolumn за замовчуванням (strroll ('% s', 'now'))
larham1

1
"... за замовчуванням (strearch ('% s', 'now'))" не є константним виразом, не працюватиме за умовчанням, надаючи "Помилка: значення стовпця [...] за замовчуванням не є постійним".
Мірек Русін

@mckoss приємно, але SQLite ігнорує "(4)" після "INTEGER". Документація на SQLite: типи даних У версії 3 SQLite сказано: "числові аргументи в дужках, які слідують за іменем типу ... ігноруються SQLite", і що кількість байтів, використаних для зберігання значення класу зберігання "INTEGER", залежить "від величини значення ". Отже, я думаю, ти маєш рацію, що SQLite зберігає його всього з 4 байтами, але до 2038 року йому доведеться використовувати 6 байт - сподіваємось, комп’ютери можуть кодувати до цього моменту
ma11hew28

94

за словами д-ра. хіп у недавньому списку публікації:

CREATE TABLE whatever(
     ....
     timestamp DATE DEFAULT (datetime('now','localtime')),
     ...
);

Дуже дякую! Я не був задоволений форматом, CURRENT_TIMESTAMPтому я створив власну функцію в C, щоб повернути кількість мікросекунд після Епохи, і я радий, що можу використовувати це як DEFAULTзараз.
Майкл

39

Це просто синтаксична помилка, вам потрібні дужки: (DATETIME('now'))

Якщо ви подивитеся на документацію , ви помітите круглі дужки, які додаються навколо параметра "expr" у синтаксисі.


18

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

Використання епохи unix економить простір пам’яті - 4 байти, ціле число проти 24 байтових рядків при зберіганні у вигляді рядка ISO8601, див . Типи даних . Якщо 4 байти недостатньо, їх можна збільшити до 6 або 8 байт.

Збереження часової позначки в часовому поясі UTC дозволяє зручно показувати розумне значення на кількох часових поясах.

Версія SQLite 3.8.6, яка постачається з Ubuntu LTS 14.04.

$ sqlite3 so.db
SQLite version 3.8.6 2014-08-15 11:46:33
Enter ".help" for usage hints.
sqlite> .headers on

create table if not exists example (
   id integer primary key autoincrement
  ,data text not null unique
  ,created_at integer(4) not null default (strftime('%s','now'))
);

insert into example(data) values
 ('foo')
,('bar')
;

select
 id
,data
,created_at as epoch
,datetime(created_at, 'unixepoch') as utc
,datetime(created_at, 'unixepoch', 'localtime') as localtime
from example
order by id
;

id|data|epoch     |utc                |localtime
1 |foo |1412097842|2014-09-30 17:24:02|2014-09-30 20:24:02
2 |bar |1412097842|2014-09-30 17:24:02|2014-09-30 20:24:02

Місцевий час правильний, оскільки в момент запиту я розташований у UTC + 2 DST.


7

Можливо, краще використовувати тип REAL, щоб заощадити місце для зберігання.

Цитата з розділу 1.2 Типи даних у версії 3 SQLite

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

CREATE TABLE test (
    id INTEGER PRIMARY KEY AUTOINCREMENT, 
    t REAL DEFAULT (datetime('now', 'localtime'))
);

див. стовпчик-обмеження .

І вставити рядок, не надаючи значення.

INSERT INTO "test" DEFAULT VALUES;

1
Я вважаю за краще, integer(n)де можна вибрати відповідне значення n.
користувач272735

4

Це синтаксична помилка, оскільки ви не написали дужки

якщо ти пишеш

Виберіть datetime ("зараз"), тоді він дасть вам utc час, але якщо ви це напишіть, це запит, тоді ви повинні додати дужки до цього так (datetime ('now')) для UTC Time. для місцевого часу ж Виберіть дата для запиту ("зараз", "місцевий час")

(дата ("зараз", "місцевий час"))


1

Цей альтернативний приклад зберігає місцевий час як Integer, щоб зберегти 20 байт. Робота виконується в полях за замовчуванням, Триггеру оновлення та Перегляді. strroll повинен використовувати '% s' (одинарні лапки), оскільки "% s" (подвійні лапки) наклав на мене помилку "Не постійний".

Create Table Demo (
   idDemo    Integer    Not Null Primary Key AutoIncrement
  ,DemoValue Text       Not Null Unique
  ,DatTimIns Integer(4) Not Null Default (strftime('%s', DateTime('Now', 'localtime'))) -- get Now/UTC, convert to local, convert to string/Unix Time, store as Integer(4)
  ,DatTimUpd Integer(4)     Null
);

Create Trigger trgDemoUpd After Update On Demo Begin
  Update Demo Set
    DatTimUpd  =                          strftime('%s', DateTime('Now', 'localtime'))  -- same as DatTimIns
  Where idDemo = new.idDemo;
End;

Create View If Not Exists vewDemo As Select -- convert Unix-Times to DateTimes so not every single query needs to do so
   idDemo
  ,DemoValue
  ,DateTime(DatTimIns, 'unixepoch') As DatTimIns -- convert Integer(4) (treating it as Unix-Time)
  ,DateTime(DatTimUpd, 'unixepoch') As DatTimUpd --   to YYYY-MM-DD HH:MM:SS
From Demo;

Insert Into Demo (DemoValue) Values ('One');                      -- activate the field Default
-- WAIT a few seconds --    
Insert Into Demo (DemoValue) Values ('Two');                      -- same thing but with
Insert Into Demo (DemoValue) Values ('Thr');                      --   later time values

Update Demo Set DemoValue = DemoValue || ' Upd' Where idDemo = 1; -- activate the Update-trigger

Select * From    Demo;                                            -- display raw audit values
idDemo  DemoValue  DatTimIns   DatTimUpd
------  ---------  ----------  ----------
1       One Upd    1560024902  1560024944
2       Two        1560024944
3       Thr        1560024944

Select * From vewDemo;                                            -- display automatic audit values
idDemo  DemoValue  DatTimIns            DatTimUpd
------  ---------  -------------------  -------------------
1       One Upd    2019-06-08 20:15:02  2019-06-08 20:15:44
2       Two        2019-06-08 20:15:44
3       Thr        2019-06-08 20:15:44
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.