Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ALTERing a sqlite table to add a timestamp column with default value

It isn't possible to ALTER table ADD column foo timestamp default CURRENT_TIMESTAMP in sqlite, but are there any clever workarounds?

like image 615
user3791372 Avatar asked Sep 18 '14 11:09

user3791372


People also ask

How do I add a default value to a timestamp column?

Use of DEFAULT CURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP is specific to TIMESTAMP. The DEFAULT clause also can be used to specify a constant (nonautomatic) default value; for example, DEFAULT 0 or DEFAULT '2000-01-01 00:00:00'.

How do I create a date column in SQLite?

First, create a new table named datetime_real . Second, insert the “current” date and time value into the datetime_real table. We used the julianday() function to convert the current date and time to the Julian Day. Third, query data from the datetime_real table.

Can you modify any table in any way or are there limits SQLite?

SQLite supports a limited subset of ALTER TABLE. The ALTER TABLE command in SQLite allows these alterations of an existing table: it can be renamed; a column can be renamed; a column can be added to it; or a column can be dropped from it.

Does SQLite support timestamp?

SQLite does not have a storage class set aside for storing dates and/or times. Instead, the built-in Date And Time Functions of SQLite are capable of storing dates and times as TEXT, REAL, or INTEGER values: TEXT as ISO8601 strings ("YYYY-MM-DD HH:MM:SS. SSS").


1 Answers

SQLite does not actually modify the table contents when adding a column, so the default must be a value that does not require reading the table.

To work around this, you could use a trigger instead of a default value:

  1. Add the column without the default value:

    ALTER TABLE MyTable ADD COLUMN foo timestamp DEFAULT NULL;
    
  2. Use a trigger to set the default value:

    ADD TRIGGER MyTable_foo_default
    AFTER INSERT ON MyTable
    FOR EACH ROW
    WHEN NEW.foo IS NULL
    BEGIN
        UPDATE MyTable
        SET foo = CURRENT_TIMESTAMP
        WHERE rowid = NEW.rowid;
    END;
    

Alternatively, modify the table contents first so that all rows have a value, then set the default value:

  1. Add the column without the default value:

    ALTER TABLE MyTable ADD COLUMN foo timestamp DEFAULT NULL /* replace me */;
    
  2. Set the column value to something in all rows (the actual value does not matter, the important thing is that all rows now have the new column):

    UPDATE MyTable SET foo = CURRENT_TIMESTAMP;
    
  3. Change the default value (documentation: PRAGMA writable_schema, sqlite_master):

    PRAGMA writable_schema = on;
    
    UPDATE sqlite_master
    SET sql = replace(sql, 'DEFAULT NULL /* replace me */',
                           'DEFAULT CURRENT_TIMESTAMP')
    WHERE type = 'table'
      AND name = 'MyTable';
    
    PRAGMA writable_schema = off;
    
  4. Reopen the database (otherwise, SQLite won't know about the new default value).
like image 53
CL. Avatar answered Oct 20 '22 21:10

CL.