如何在SQLite中具有自动时间戳?


131

我有一个SQLite数据库,版本3,并且我正在使用C#创建使用该数据库的应用程序。

我想在表中使用时间戳字段进行并发,但是我注意到当我插入新记录时,此字段未设置,并且为null。

例如,在MS SQL Server中,如果我使用一个时间戳字段,该字段由数据库更新,则不必自己设置。在SQLite中这可能吗?

Answers:


211

只需为字段声明默认值即可:

CREATE TABLE MyTable(
    ID INTEGER PRIMARY KEY,
    Name TEXT,
    Other STUFF,
    Timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
);

但是,如果您的INSERT命令将该字段显式设置为NULL,则它将设置为NULL


5
这不是完全等同于SQL Server的时间戳,因为它基于系统时钟。如果更改时钟,则该值可能会倒退。在SQL Server中,时间戳记值始终在递增。
罗里·麦克劳德

25
@Matthieu没有DATETIME 数据类型,但是SQLite接受任何内容作为字段类型。
CL。

4
@Matthieu在您提供的链接中,SQLite中提到了DATETIME数据类型。阅读2.2亲和名称的例子
拉菲克·穆罕默德

6
这似乎并不涵盖UPDATE语句。看起来触发器是执行此操作的唯一方法。
戴尔·安德森

2
@CL抱歉,您是对的。我不正确地合并了您的答案和不满意的答案。随着DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW', 'localtime'))一个实际上得到有意义的微秒值。
Dietmar

70

您可以在SQLite的表中创建TIMESTAMP字段,请参见以下内容:

CREATE TABLE my_table (
    id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
    name VARCHAR(64),
    sqltime TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
);

INSERT INTO my_table(name, sqltime) VALUES('test1', '2010-05-28T15:36:56.200');
INSERT INTO my_table(name, sqltime) VALUES('test2', '2010-08-28T13:40:02.200');
INSERT INTO my_table(name) VALUES('test3');

结果如下:

SELECT * FROM my_table;

在此处输入图片说明


无法添加具有非恒定默认值的列(ALTER TABLE“ main”。“ xxx_data”添加列“ created_date” TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP)
toing_toing

13

读取datefunc一个自动完成日期时间的工作示例是:

sqlite> CREATE TABLE 'test' ( 
   ...>    'id' INTEGER PRIMARY KEY,
   ...>    'dt1' DATETIME NOT NULL DEFAULT (datetime(CURRENT_TIMESTAMP, 'localtime')), 
   ...>    'dt2' DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%d %H:%M:%S', 'now', 'localtime')), 
   ...>    'dt3' DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%d %H:%M:%f', 'now', 'localtime'))
   ...> );

让我们以初始化自动完成日期时间的方式插入一些行:

sqlite> INSERT INTO 'test' ('id') VALUES (null);
sqlite> INSERT INTO 'test' ('id') VALUES (null);

存储的数据清楚地表明前两个相同,但第三个功能不同:

sqlite> SELECT * FROM 'test';
1|2017-09-26 09:10:08|2017-09-26 09:10:08|2017-09-26 09:10:08.053
2|2017-09-26 09:10:56|2017-09-26 09:10:56|2017-09-26 09:10:56.894

请注意,SQLite函数用括号括起来!在一个示例中展示它有多困难?

玩得开心!


7

您可以使用触发器。效果很好

CREATE TABLE MyTable(
ID INTEGER PRIMARY KEY,
Name TEXT,
Other STUFF,
Timestamp DATETIME);


CREATE TRIGGER insert_Timestamp_Trigger
AFTER INSERT ON MyTable
BEGIN
   UPDATE MyTable SET Timestamp =STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') WHERE id = NEW.id;
END;

CREATE TRIGGER update_Timestamp_Trigger
AFTER UPDATE On MyTable
BEGIN
   UPDATE MyTable SET Timestamp = STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') WHERE id = NEW.id;
END;

6

为了补充上面的答案...

如果您使用的是EF,请使用数据注释[Timestamp]装饰该属性,然后转到上下文类内部的重写的OnModelCreating,并添加以下Fluent API代码:

modelBuilder.Entity<YourEntity>()
                .Property(b => b.Timestamp)
                .ValueGeneratedOnAddOrUpdate()
                .IsConcurrencyToken()
                .ForSqliteHasDefaultValueSql("CURRENT_TIMESTAMP");

对于将插入到该表中的每个数据,它将采用默认值。


知道Entity在Xamarin应用中如何在Android上执行吗?还没有进行测试,但是用DAL代替会很好。
samis

我找不到sqliteHasDefault所需的软件包。您知道我必须从nuget获得哪个软件包?
Simons0n

@ Simons0n,尝试使用此Microsoft.EntityFrameworkCore.Metadata.Builders.PropertyBuilder命名空间。
拉斐尔

2

您可以通过以下方式使用自定义日期时间:

 create table noteTable3 
 (created_at DATETIME DEFAULT (STRFTIME('%d-%m-%Y   %H:%M', 'NOW','localtime')),
 title text not null, myNotes text not null);

使用“ NOW”,“ localtime”获取当前系统日期,否则它将在数据库中插入时间之后显示数据库中的过去或其他时间。

谢谢...


1
如果需要微秒,则很有用;您可以使用DEFAULT(STRFTIME('%Y-%m-%d%H:%M:%f','NOW','localtime')))。仅说DEFAULT CURRENT_TIMESTAMP只会给您1秒的粒度。
Dietmar

这绝对有效!注意strftime(),因为它用括号括起来了!
centurian

0

如果您使用SQLite DB浏览器,则可以通过以下方式更改默认值:

  1. 选择数据库结构
  2. 选择表
  3. 修改表
  4. 在您的列中的“默认值”下输入值:=(datetime('now','localtime'))

我建议您先对数据库进行更新,因为该值的格式错误可能会导致SQLLite浏览器出现问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.