Значение по умолчанию для базы данных 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) (strftime ("% s", CURRENT_TIME)); "
mckoss
3
@mckoss благодаря вашему комментарию оператор create стал: ... mycolumn default (strftime ('% s', 'now'))
larham1
1
"... default (strftime ('% s', 'now'))" не является константным выражением, не будет работать со значением по умолчанию, дающим "Ошибка: значение по умолчанию для столбца [...] не является постоянным".
Мирек Русин
@mckoss приятно, но SQLite игнорирует "(4)" после "INTEGER". Документация по SQLite: типы данных В SQLite версии 3 говорится «числовые аргументы в скобках, которые следуют после имени типа ... игнорируются SQLite» и что число байтов, используемых для хранения значения класса хранения «INTEGER», зависит «от величины стоимости ". Так что , я думаю , вы правы , что SQLite будет хранить его только 4 байта, а в 2038 году, он должен был бы использовать 6 байт-Надеются, компьютеры могут кодировать тогдашние и 8 байт со стороны 4461642. года
ma11hew28
94

в соответствии с др. hipp в недавнем сообщении списка:

CREATE TABLE whatever(
     ....
     timestamp DATE DEFAULT (datetime('now','localtime')),
     ...
);
оборот
источник
Спасибо вам большое! Я не был удовлетворен форматом, CURRENT_TIMESTAMPпоэтому я создал свою собственную функцию в C, чтобы возвращать количество микросекунд с начала эпохи, и я рад, что могу использовать это как DEFAULTсейчас.
Майкл
39

Это просто синтаксическая ошибка, вам нужно скобки: (DATETIME('now'))

Если вы посмотрите на документацию , вы заметите круглые скобки, которые добавляются вокруг опции 'expr' в синтаксисе.

Адам Лютер
источник
18

Это полный пример, основанный на других ответах и ​​комментариях к вопросу. В этом примере отметка времени ( created_at-column) сохраняется как часовой пояс UTC эпохи Unix и преобразуется в местный часовой пояс только при необходимости.

Использование Unix Epoch экономит место для хранения - 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 на момент запроса.

user272735
источник
7

Может быть лучше использовать тип REAL, чтобы сэкономить место для хранения.

Цитата из 1.2 раздела Типы данных в SQLite версии 3

SQLite не имеет класса хранения, выделенного для хранения дат и / или времени. Вместо этого встроенные функции даты и времени в SQLite могут сохранять даты и время в виде значений TEXT, REAL или INTEGER.

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

см. столбец-ограничение .

И вставить строку, не предоставляя никакого значения.

INSERT INTO "test" DEFAULT VALUES;
Nianliang
источник
1
Я предпочитаю, integer(n)где можно выбрать подходящее значение для n.
user272735
4

Это ошибка синтаксиса, потому что вы не написали круглые скобки

если ты пишешь

Выберите datetime («сейчас»), тогда он даст вам время, но если вы напишете запрос, то перед этим необходимо добавить круглые скобки (datetime («сейчас»)) для времени UTC. для местного времени то же самое Выберите datetime ('now', 'localtime') для запроса

(Даты и времени ( 'теперь', 'LocalTime'))

Sandeep
источник
1

Этот альтернативный пример хранит местное время как целое число, чтобы сохранить 20 байтов. Работа выполняется в полях default, Update-trigger и View. strftime должен использовать «% 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
ножные кандалы
источник