giá trị thời gian mặc định của cơ sở dữ liệu sqlite 'ngay bây giờ'


190

Có thể trong cơ sở dữ liệu sqlite để vượt qua một bảng có cột dấu thời gian mặc định DATETIME('now')không?

Như thế này:

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

Điều này đưa ra một lỗi ... Làm thế nào để giải quyết?

Câu trả lời:


290

tôi tin bạn có thể sử dụng

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

kể từ phiên bản 3.1 ( nguồn )


22
Nếu bạn lo ngại về kích thước lưu trữ, lưu ý rằng công thức này sẽ lưu dấu thời gian của bạn ở ISO-8601 (định dạng văn bản), chiếm khoảng 24 byte trong cơ sở dữ liệu mỗi ngày. Bạn có thể tiết kiệm dung lượng chỉ bằng cách sử dụng cột INTEGER (4) và lưu trữ thời gian unix thông qua các giá trị "INSERT INTO test (t) (strftime ("% s ", CURRENT_TIME));"
mckoss

3
@mckoss nhờ nhận xét của bạn, câu lệnh tạo đã trở thành: ... mycolumn mặc định (strftime ('% s', 'now'))
larham1

1
"... mặc định (strftime ('% s', 'now'))" không phải là biểu thức không đổi, sẽ không hoạt động với mặc định "Lỗi: giá trị mặc định của cột [...] không phải là hằng số".
Mirek Rusin

@mckoss đẹp, nhưng SQLite bỏ qua "(4)" sau "INTEGER". Tài liệu SQLite: Các kiểu dữ liệu Trong SQLite Phiên bản 3 cho biết "các đối số số trong ngoặc đơn theo tên loại .. Được bỏ qua bởi SQLite" và số byte được sử dụng để lưu trữ giá trị của lớp lưu trữ "INTEGER" phụ thuộc vào "độ lớn" của giá trị ". Vì vậy, tôi nghĩ rằng bạn đúng rằng SQLite sẽ lưu trữ nó chỉ với 4 byte, nhưng đến năm 2038, nó sẽ phải sử dụng 6 byte. Hy vọng, các máy tính có thể mã hóa sau đó bằng cách và 8 byte vào năm 4461642.
ma11hew28

94

theo dr. hipp trong một bài đăng danh sách gần đây:

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

Cảm ơn bạn rất nhiều! Tôi không hài lòng với định dạng của CURRENT_TIMESTAMPnó vì vậy tôi đã tạo chức năng của riêng mình trong C để trả về số micrô giây kể từ Kỷ nguyên, và tôi rất vui vì bây giờ tôi có thể sử dụng chức năng đó DEFAULT.
Michael

39

Đó chỉ là một lỗi cú pháp, bạn cần dấu ngoặc đơn: (DATETIME('now'))

Nếu bạn xem tài liệu , bạn sẽ lưu ý dấu ngoặc đơn được thêm vào xung quanh tùy chọn 'expr' trong cú pháp.


18

Đây là một ví dụ đầy đủ dựa trên các câu trả lời và nhận xét khác cho câu hỏi. Trong ví dụ, dấu thời gian ( created_at-column) được lưu dưới dạng múi giờ UTC unix epoch và chỉ được chuyển đổi thành múi giờ cục bộ khi cần thiết.

Sử dụng unix epoch giúp tiết kiệm không gian lưu trữ - số nguyên 4 byte so với chuỗi 24 byte khi được lưu dưới dạng chuỗi ISO8601, xem kiểu dữ liệu . Nếu 4 byte là không đủ có thể tăng lên 6 hoặc 8 byte.

Lưu dấu thời gian trên múi giờ UTC giúp thuận tiện hiển thị giá trị hợp lý trên nhiều múi giờ.

Phiên bản SQLite là 3.8.6 đi kèm với 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

Giờ địa phương là chính xác vì tôi đang ở UTC + 2 DST tại thời điểm truy vấn.


7

Có thể tốt hơn để sử dụng loại REAL, để tiết kiệm không gian lưu trữ.

Trích dẫn từ 1,2 phần của kiểu dữ liệu trong SQLite Phiên bản 3

SQLite không có lớp lưu trữ được dành riêng để lưu trữ ngày và / hoặc thời gian. Thay vào đó, Hàm ngày và giờ tích hợp của SQLite có khả năng lưu trữ ngày và giờ dưới dạng giá trị TEXT, REAL hoặc INTEGER

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

xem ràng buộc cột .

chèn một hàng mà không cung cấp bất kỳ giá trị.

INSERT INTO "test" DEFAULT VALUES;

1
Tôi thích integer(n)nơi người ta có thể chọn giá trị phù hợp cho n.
dùng272735

4

Đó là lỗi cú pháp vì bạn không viết dấu ngoặc đơn

nếu bạn viết

Chọn datetime ('now') sau đó nó sẽ cung cấp cho bạn thời gian utc nhưng nếu bạn viết nó truy vấn thì bạn phải thêm dấu ngoặc đơn trước đó để (datetime ('now')) cho UTC Time. cho giờ địa phương giống nhau Chọn datetime ('now', 'localtime') cho truy vấn

(ngày giờ ('bây giờ', 'giờ địa phương'))


1

Ví dụ thay thế này lưu trữ thời gian cục bộ dưới dạng Integer để lưu 20 byte. Công việc được thực hiện trong trường mặc định, Cập nhật kích hoạt và Xem. strftime phải sử dụng '% s' (dấu ngoặc đơn) vì "% s" (dấu ngoặc kép) đã gây ra lỗi 'Không liên tục' đối với tôi.

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.