181

I have an SQLite database, version 3 and I am using C# to create an application that uses this database.

I want to use a timestamp field in a table for concurrency, but I notice that when I insert a new record, this field is not set, and is null.

For example, in MS SQL Server if I use a timestamp field it is updated by the database and I don't have to set it by myself. Is this possible in SQLite?

Saurabh
  • 5,176
  • 4
  • 32
  • 46
Álvaro García
  • 18,114
  • 30
  • 102
  • 193
  • Does this answer your question? [sqlite database default time value 'now'](https://stackoverflow.com/questions/200309/sqlite-database-default-time-value-now) – user4157124 Jul 03 '22 at 17:05

7 Answers7

287

Just declare a default value for a field:

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

However, if your INSERT command explicitly sets this field to NULL, it will be set to NULL.

Community
  • 1
  • 1
CL.
  • 173,858
  • 17
  • 217
  • 259
  • 7
    That's not quite equivalent to SQL Server's timestamp because it's based on the system clock; if you change the clock, the value could go backwards. In SQL Server, timestamp values are always incrementing. – Rory MacLeod May 08 '13 at 15:21
  • 39
    @Matthieu There is no `DATETIME` *data* type, but SQLite accepts anything as *field* type. – CL. Jun 24 '13 at 16:10
  • 4
    @Matthieu There is DATETIME datatype mentioned in SQLite in the link which u have provided. Read 2.2 Affinity Name Examples – Rafique Mohammed Mar 13 '15 at 12:33
  • 8
    This doesn't seem to cover UPDATE statements. It looks like a trigger is the only way to do this. – Dale Anderson Mar 30 '16 at 21:07
  • 1
    This will give you a granularity of one second. If you care about microseconds, you can use `DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', CURRENT_TIMESTAMP))`. – Dietmar Jun 22 '17 at 13:47
  • 1
    @Dietmar That just adds three zeros … – CL. Jun 22 '17 at 14:10
  • 5
    @CL Sorry, you're right. I incorrectly merged your answer and javed's. With `DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW', 'localtime'))` one actually gets meaningful microsecond values. – Dietmar Jun 22 '17 at 18:24
  • 2
    "if your INSERT command explicitly sets this field to NULL, it will be set to NULL" ... this is true until you set a not-null constraint on the field. Strangely this constraint causes sqlite3 to use the default. – DAG May 07 '21 at 17:42
  • 2
    And here is the link to the documentation where this CURRENT_TIMESTAMP is explained, maybe it will be useful for someone. https://www.sqlite.org/lang_createtable.html#the_default_clause What's interesting - it's not a function, it's just a keyword. https://www.sqlite.org/lang_keywords.html – Rocckk Nov 23 '21 at 10:21
83

You can create TIMESTAMP field in table on the SQLite, see this:

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');

This is the result:

SELECT * FROM my_table;

enter image description here

halfer
  • 19,824
  • 17
  • 99
  • 186
SBotirov
  • 13,872
  • 7
  • 59
  • 81
  • Cannot add a column with non-constant default (ALTER TABLE "main"."xxx_data" ADD COLUMN "created_date" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP) – toing_toing Mar 27 '19 at 14:20
  • 1
    TIMESTAMP is not a real type in SQLite. Their documentation for type affinity uses DATETIME. – sproketboy Feb 09 '21 at 11:00
23

Reading datefunc a working example of automatic datetime completion would be:

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'))
   ...> );

Let's insert some rows in a way that initiates automatic datetime completion:

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

The stored data clearly shows that the first two are the same but not the third function:

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

Pay attention that SQLite functions are surrounded in parenthesis! How difficult was this to show it in one example?

Have fun!

centurian
  • 1,168
  • 13
  • 25
14

you can use triggers. works very well

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;
Rahmat Anjirabi
  • 868
  • 13
  • 16
  • 1
    Uhmm I have created two fields separately, `create_date` and `write_date`. I have used your code and I get the error "too many levels of trigger recursion". I had to exclude the `write_date` from the `update` trigger by adding a clause `UPDATE OF`. I hope that is the correct way to do it – ChesuCR Jun 02 '22 at 15:16
  • Besides, I think Timestamp field should be TEXT because DATETIME type does not exist in SQLite – ChesuCR Jun 02 '22 at 15:17
7

To complement answers above...

If you are using EF, adorn the property with Data Annotation [Timestamp], then go to the overrided OnModelCreating, inside your context class, and add this Fluent API code:

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

It will make a default value to every data that will be insert into this table.

Rafael
  • 966
  • 12
  • 22
  • I do not find the package that is needed for the sqliteHasDefault. You you know which package I have to get from nuget? – modmoto Oct 23 '18 at 22:49
  • @Simons0n, try to use this Microsoft.EntityFrameworkCore.Metadata.Builders.PropertyBuilder namespace. – Rafael Oct 24 '18 at 18:57
5

you can use the custom datetime by using...

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

use 'NOW','localtime' to get the current system date else it will show some past or other time in your Database after insertion time in your db.

Thanks You...

Javed
  • 1,613
  • 17
  • 16
  • 2
    Useful if you need microseconds; you can use DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW','localtime'))`. Just saying DEFAULT CURRENT_TIMESTAMP will only give you a granularity of one second. – Dietmar Jun 22 '17 at 18:26
3

If you use the SQLite DB-Browser you can change the default value in this way:

  1. Choose database structure
  2. select the table
  3. modify table
  4. in your column put under 'default value' the value: =(datetime('now','localtime'))

I recommend to make an update of your database before, because a wrong format in the value can lead to problems in the SQLLite Browser.

SJX
  • 1,071
  • 14
  • 15
  • And if it complains about not being able to add a new column with a given default value, then (1) just add the column without any default value, (2) save, (3) modify the table again and enter the default value for the column created in step 1. – Magnus Dec 03 '20 at 20:24