nilai waktu default sqlite database 'sekarang'

190

Apakah mungkin dalam database sqlite untuk membuat tabel yang memiliki kolom stempel waktu yang standarnya DATETIME('now')?

Seperti ini:

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

Ini memberikan kesalahan ... Bagaimana mengatasinya?

Joep
sumber

Jawaban:

291

saya yakin Anda bisa menggunakannya

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

pada versi 3.1 ( sumber )

Owen
sumber
22
Jika Anda khawatir tentang ukuran penyimpanan, perhatikan bahwa resep ini akan menyimpan stempel waktu Anda di ISO-8601 (format teks), menghabiskan sekitar 24 byte dalam database per tanggal. Anda dapat menghemat ruang hanya dengan menggunakan kolom INTEGER (4), dan menyimpan waktu unix melalui "INSERT INTO test (t) nilai (strftime ("% s ", CURRENT_TIME));"
mckoss
3
@mckoss terima kasih atas komentar Anda, pernyataan create menjadi: ... default mycolumn (strftime ('% s', 'now'))
larham1
1
"... default (strftime ('% s', 'now'))" bukan ekspresi konstan, tidak akan berfungsi dengan pemberian default "Kesalahan: nilai default kolom [...] tidak konstan".
Mirek Rusin
@ Mattoss bagus, tapi SQLite mengabaikan "(4)" setelah "INTEGER". Dokumentasi SQLite: Datatypes Dalam SQLite Version 3 mengatakan "argumen numerik dalam tanda kurung yang mengikuti nama tipe ... diabaikan oleh SQLite" dan bahwa jumlah byte yang digunakan untuk menyimpan nilai kelas penyimpanan "INTEGER" tergantung "pada besarnya dari nilai ". Jadi, saya pikir Anda benar bahwa SQLite akan menyimpannya hanya dengan 4 byte, tetapi pada tahun 2038, ia harus menggunakan 6 byte — Mudah-mudahan, komputer dapat membuat kode pada saat itu — dan 8 byte pada tahun 4461642.
ma11hew28
94

menurut dr. hipp di posting daftar terbaru:

CREATE TABLE whatever(
     ....
     timestamp DATE DEFAULT (datetime('now','localtime')),
     ...
);
putaran
sumber
Terima kasih banyak! Saya tidak puas dengan format CURRENT_TIMESTAMPjadi saya membuat fungsi saya sendiri di C untuk mengembalikan jumlah mikrodetik sejak Zaman, dan saya senang saya bisa menggunakannya sebagai DEFAULTsekarang.
Michael
39

Itu hanya kesalahan sintaksis, Anda perlu tanda kurung: (DATETIME('now'))

Jika Anda melihat dokumentasi , Anda akan mencatat tanda kurung yang ditambahkan di sekitar opsi 'expr' dalam sintaksis.

Adam Luter
sumber
18

Ini adalah contoh lengkap berdasarkan jawaban dan komentar lain untuk pertanyaan itu. Dalam contoh cap waktu ( created_at-kolom) disimpan sebagai zona waktu UTC unix epoch dan dikonversi ke zona waktu lokal hanya bila diperlukan.

Menggunakan unix epoch menghemat ruang penyimpanan - bilangan bulat 4 byte vs 24 byte saat disimpan sebagai string ISO8601, lihat tipe data . Jika 4 byte tidak cukup yang dapat ditingkatkan menjadi 6 atau 8 byte.

Menyimpan stempel waktu di zona waktu UTC memudahkan untuk menampilkan nilai yang masuk akal pada beberapa zona waktu.

Versi SQLite adalah 3.8.6 yang disertakan bersama 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

Localtime sudah benar karena saya berlokasi di UTC + 2 DST pada saat permintaan.

pengguna272735
sumber
7

Mungkin lebih baik menggunakan tipe REAL, untuk menghemat ruang penyimpanan.

Kutipan dari 1.2 bagian Datatypes Dalam SQLite Versi 3

SQLite tidak memiliki kelas penyimpanan yang disisihkan untuk menyimpan tanggal dan / atau waktu. Alih-alih, Fungsi Tanggal dan Waktu bawaan SQLite mampu menyimpan tanggal dan waktu sebagai nilai TEKS, NYATA, atau INTEGER

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

lihat kendala kolom .

Dan masukkan baris tanpa memberikan nilai apa pun.

INSERT INTO "test" DEFAULT VALUES;
Nianliang
sumber
1
Saya lebih suka di integer(n)mana orang dapat memilih nilai yang cocok untuk n.
user272735
4

Ini adalah kesalahan sintaksis karena Anda tidak menulis tanda kurung

jika kamu menulis

Pilih datetime ('sekarang') maka itu akan memberi Anda waktu utc tetapi jika Anda ini menulis kueri maka Anda harus menambahkan tanda kurung sebelum ini jadi (datetime ('sekarang')) untuk Waktu UTC. untuk waktu lokal yang sama Pilih datetime ('sekarang', 'localtime') untuk permintaan

(datetime ('now', 'localtime'))

Sandeep
sumber
1

Contoh alternatif ini menyimpan waktu lokal sebagai Integer untuk menghemat 20 byte. Pekerjaan dilakukan di bidang default, Perbarui-memicu, dan Lihat. strftime harus menggunakan '% s' (tanda kutip tunggal) karena "% s" (tanda kutip ganda) melemparkan kesalahan 'Tidak Konstan' pada saya.

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
Pedang Spanyol
sumber