ค่าเวลาเริ่มต้นของฐานข้อมูล sqlite 'ตอนนี้'


190

เป็นไปได้ในฐานข้อมูล sqlite เพื่อ craete ตารางที่มีคอลัมน์เวลาที่เริ่มต้น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 ขอบคุณสำหรับความคิดเห็นของคุณคำสั่งสร้างกลายเป็น: ... ค่าเริ่มต้น mycolumn (strftime ('% s', 'now'))
larham1

1
"... ค่าเริ่มต้น (strftime ('% s', 'now'))" ไม่ใช่นิพจน์คงที่จะไม่ทำงานกับค่าเริ่มต้นที่ให้ "ข้อผิดพลาด: ค่าเริ่มต้นของคอลัมน์ [... ] ไม่คงที่"
Mirek Rusin

@mckoss ดี แต่ SQLite จะละเว้น "(4)" หลัง "INTEGER" เอกสารประกอบ SQLite: ประเภทข้อมูลใน SQLite เวอร์ชัน 3กล่าวว่า "อาร์กิวเมนต์ตัวเลขในวงเล็บที่ตามด้วยชื่อประเภท... จะถูกละเว้นโดย SQLite" และจำนวนไบต์ที่ใช้ในการจัดเก็บค่าของคลาสหน่วยเก็บข้อมูล "INTEGER" ขึ้นอยู่กับขนาด ของค่า " ดังนั้นฉันคิดว่าคุณคิดถูกว่า SQLite จะเก็บมันด้วย 4 ไบต์เท่านั้น แต่ภายในปี 2581 มันจะต้องใช้ 6 ไบต์หวังว่าคอมพิวเตอร์จะสามารถเขียนโค้ดได้ในตอนนั้นและ 8 ไบต์ในปี 4461642
ma11hew28

94

ตามที่ดร. hipp ในรายการโพสต์ล่าสุด:

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

ขอบคุณมาก! ฉันไม่พอใจกับรูปแบบของCURRENT_TIMESTAMPดังนั้นฉันจึงสร้างฟังก์ชันของตัวเองใน C เพื่อคืนจำนวน microseconds ตั้งแต่ Epoch และฉันดีใจที่ฉันสามารถใช้มันเป็นDEFAULTตอนนี้
Michael

39

มันเป็นเพียงข้อผิดพลาดทางไวยากรณ์คุณต้องการวงเล็บ: (DATETIME('now'))

หากคุณดูเอกสารคุณจะสังเกตเห็นวงเล็บที่เพิ่มรอบตัวเลือก 'expr' ในไวยากรณ์


18

นี่คือตัวอย่างเต็มรูปแบบตามคำตอบและความคิดเห็นอื่น ๆ ของคำถาม ในตัวอย่างการประทับเวลา ( created_at-column) ถูกบันทึกเป็นเขตเวลาunix epoch UTC และแปลงเป็นเขตเวลาท้องถิ่นเมื่อจำเป็นเท่านั้น

ใช้ยูนิกซ์ยุคประหยัดพื้นที่การจัดเก็บ - 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 ของประเภทข้อมูลใน SQLite เวอร์ชัน 3

SQLite ไม่มีคลาสหน่วยเก็บข้อมูลสำหรับการจัดเก็บวันที่และ / หรือเวลา แต่ฟังก์ชัน Date and Time ในตัวของ 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 สำหรับเวลาท้องถิ่นเหมือนกันเลือกวันที่และเวลา ('ตอนนี้', 'เวลาท้องถิ่น') เพื่อสอบถาม

(วันที่และเวลา ( 'ตอนนี้', 'localtime'))


1

ตัวอย่างทางเลือกนี้เก็บเวลาท้องถิ่นเป็นจำนวนเต็มเพื่อบันทึก 20 ไบต์ งานจะดำเนินการในฟิลด์เริ่มต้น 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.