valor do tempo padrão do banco de dados sqlite 'now'


190

É possível em um banco de dados sqlite criar uma tabela que tenha uma coluna de carimbo de data / hora padrão para isso DATETIME('now')?

Como isso:

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

Isso dá um erro ... Como resolver?

Respostas:


290

eu acredito que você pode usar

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

a partir da versão 3.1 ( fonte )


22
Se você está preocupado com o tamanho do armazenamento, observe que esta receita salvará seus carimbos de data / hora no formato ISO-8601 (um formato de texto), ocupando cerca de 24 bytes no banco de dados por data. Você pode economizar espaço usando apenas uma coluna INTEGER (4) e armazenando o tempo unix através de "INSERT INTO test (t) values ​​(strftime ("% s ", CURRENT_TIME));"
Mckoss

3
@mckoss, graças ao seu comentário, a instrução create tornou-se: ... mycolumn default (strftime ('% s', 'now'))
larham1

1
"... default (strftime ('% s', 'now'))" não é expressão constante, não funcionará com o padrão dando "Erro: o valor padrão da coluna [...] não é constante".
Mirek Rusin

@mckoss bom, mas SQLite ignora o "(4)" depois de "INTEGER". Documentação do SQLite: tipos de dados No SQLite, a versão 3 diz "argumentos numéricos entre parênteses que após o nome do tipo ... são ignorados pelo SQLite" e que o número de bytes usados ​​para armazenar um valor da classe de armazenamento "INTEGER" depende "da magnitude do valor ". Então, acho que você está certo que o SQLite o armazenaria com apenas 4 bytes, mas até 2038, ele teria que usar 6 bytes - espero que os computadores possam codificar até então - e 8 bytes até o ano 4461642.
ma11hew28 07/07/19

94

de acordo com o dr. hipp em uma postagem recente na lista:

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

Muito obrigado! Como não estava satisfeito com o formato, CURRENT_TIMESTAMPcriei minha própria função em C para retornar o número de microssegundos desde a época, e estou feliz por poder usá-la DEFAULTagora.
Michael

39

É apenas um erro de sintaxe, você precisa de parênteses: (DATETIME('now'))

Se você olhar para a documentação , notará os parênteses adicionados em torno da opção 'expr' na sintaxe.


18

Este é um exemplo completo com base nas outras respostas e comentários à pergunta. No exemplo, o registro de data e hora ( created_at-coluna) é salvo como fuso horário UTC da época unix e convertido em fuso horário local somente quando necessário.

O uso da época unix economiza espaço de armazenamento - número inteiro de 4 bytes vs. sequência de 24 bytes quando armazenado como sequência ISO8601, consulte tipos de dados . Se 4 bytes não forem suficientes, podem ser aumentados para 6 ou 8 bytes.

Salvar o carimbo de data e hora no fuso horário UTC torna conveniente mostrar um valor razoável em vários fusos horários.

A versão SQLite é a 3.8.6 que vem com o 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

A hora local está correta, pois estou localizado no UTC + 2 DST no momento da consulta.


7

Pode ser melhor usar o tipo REAL, para economizar espaço de armazenamento.

Citação da seção 1.2 de Tipos de dados no SQLite versão 3

O SQLite não possui uma classe de armazenamento reservada para armazenar datas e / ou horas. Em vez disso, as funções de data e hora internas do SQLite são capazes de armazenar datas e horas como valores TEXT, REAL ou INTEGER

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

consulte restrição de coluna .

E insira uma linha sem fornecer nenhum valor.

INSERT INTO "test" DEFAULT VALUES;

1
Prefiro integer(n)onde se pode escolher o valor adequado n.
user272735

4

É um erro de sintaxe porque você não escreveu parênteses

se você escrever

Selecione datetime ('now') e, em seguida, ele fornecerá o tempo utc, mas se você o escrever, deverá adicionar parênteses antes disso (data / hora ('now')) para o horário UTC. para o horário local mesmo Selecione datetime ('now', 'localtime') para consulta

(data e hora ('agora', 'hora local'))


1

Este exemplo alternativo armazena a hora local como Inteiro para salvar os 20 bytes. O trabalho é realizado no campo padrão, gatilho de atualização e exibição. O strftime deve usar '% s' (aspas simples) porque "% s" (aspas duplas) gerou um erro 'Não constante' em mim.

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.