190

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?

1

7 Answers 7

303

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.

9
  • 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. Commented May 8, 2013 at 15:21
  • 41
    @Matthieu There is no DATETIME data type, but SQLite accepts anything as field type.
    – CL.
    Commented Jun 24, 2013 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 Commented Mar 13, 2015 at 12:33
  • 8
    This doesn't seem to cover UPDATE statements. It looks like a trigger is the only way to do this. Commented Mar 30, 2016 at 21:07
  • 7
    @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
    Commented Jun 22, 2017 at 18:24
85

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

2
  • 1
    Cannot add a column with non-constant default (ALTER TABLE "main"."xxx_data" ADD COLUMN "created_date" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP) Commented Mar 27, 2019 at 14:20
  • 3
    TIMESTAMP is not a real type in SQLite. Their documentation for type affinity uses DATETIME.
    – sproketboy
    Commented Feb 9, 2021 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!

15

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;

Update: As mentioned in the comments I tested codes on version 3.44.0, fortunately it works! why? becuase sqlite convert DATETIME datatype (from traditional SQL implementations) into NUMERIC datatype, base on determination Of Column Affinity ("https://www.sqlite.org/datatype3.html" section 3.1)

but it is better to use TEXT type instead of Datetime:

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

also tested this way, it works:).

2
  • 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
    Commented Jun 2, 2022 at 15:16
  • Besides, I think Timestamp field should be TEXT because DATETIME type does not exist in SQLite
    – ChesuCR
    Commented Jun 2, 2022 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.

2
  • I do not find the package that is needed for the sqliteHasDefault. You you know which package I have to get from nuget?
    – modmoto
    Commented Oct 23, 2018 at 22:49
  • @Simons0n, try to use this Microsoft.EntityFrameworkCore.Metadata.Builders.PropertyBuilder namespace.
    – Rafael
    Commented Oct 24, 2018 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...

1
  • 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
    Commented Jun 22, 2017 at 18:26
4

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.

1
  • 1
    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
    Commented Dec 3, 2020 at 20:24

Not the answer you're looking for? Browse other questions tagged or ask your own question.