【问题标题】:sqlite database default time value 'now'sqlite 数据库默认时间值 'now'
【发布时间】:2010-09-17 01:13:04
【问题描述】:

是否可以在 sqlite 数据库中创建具有默认为 DATETIME('now') 的时间戳列的表?

像这样:

CREATE TABLE test (
    id INTEGER PRIMARY KEY AUTOINCREMENT, 
    t TIMESTAMP DEFAULT DATETIME('now')
);

这给出了一个错误...如何解决?

【问题讨论】:

    标签: sql sqlite


    【解决方案1】:

    我相信你可以使用

    CREATE TABLE test (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      t TIMESTAMP
      DEFAULT CURRENT_TIMESTAMP
    );
    

    从 3.1 版开始 (source)

    【讨论】:

    • 如果您担心存储大小,请注意,此配方将以 ISO-8601(文本格式)保存您的时间戳,每个日期在数据库中占用大约 24 个字节。您可以仅使用 INTEGER(4) 列来节省空间,并通过“INSERT INTO test (t) values (strftime("%s", CURRENT_TIME));”存储 unix 时间。
    • @mckoss 感谢您的评论,create 语句变为: ... mycolumn default (strftime('%s','now'))
    • "... default (strftime('%s','now'))" 不是常量表达式,不能使用默认值给出“错误:列的默认值 [... ] 不是常数”。
    • @mckoss 很好,但 SQLite 忽略了“INTEGER”之后的“(4)”。 SQLite Documentation: Datatypes In SQLite Version 3 说“类型名称后面的括号中的数字参数......被 SQLite 忽略”并且用于存储“INTEGER”存储类的值的字节数取决于“值的大小”。所以,我认为 SQLite 只用 4 个字节存储它是对的,但到 2038 年,它必须使用 6 个字节——希望到那时计算机可以编码——到 4461642 年将使用 8 个字节。
    【解决方案2】:

    根据博士。 hipp 在最近的列表帖子中:

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

    【讨论】:

    • 非常感谢!我对 CURRENT_TIMESTAMP 的格式不满意,所以我在 C 中创建了自己的函数来返回自 Epoch 以来的微秒数,我很高兴现在可以将其用作 DEFAULT
    • 'localtime' 有什么原因吗?您将服务器/计算机/烤面包机向东或向西移动得太远,kaboom 就会执行您的代码。
    【解决方案3】:

    只是语法错误,需要括号:(DATETIME('now'))

    如果您查看documentation,您会注意到在语法中的“expr”选项周围添加的括号。

    【讨论】:

      【解决方案4】:

      这是一个基于问题的其他答案和 cmets 的完整示例。在示例中,时间戳 (created_at-column) 保存为 unix epoch UTC 时区,仅在必要时转换为本地时区。

      使用 unix epoch 可以节省存储空间 - 4 字节整数与 24 字节字符串存储为 ISO8601 字符串时,请参阅datatypes。如果 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。

      【讨论】:

        【解决方案5】:

        最好使用REAL类型,节省存储空间。

        引用Datatypes In SQLite Version 3的1.2部分

        SQLite 没有专门用于存储日期的存储类 和/或时间。相反,SQLite 的内置日期和时间函数 能够将日期和时间存储为 TEXT、REAL 或 INTEGER 价值观

        CREATE TABLE test (
            id INTEGER PRIMARY KEY AUTOINCREMENT, 
            t REAL DEFAULT (datetime('now', 'localtime'))
        );
        

        column-constraint

        insert一行不提供任何值。

        INSERT INTO "test" DEFAULT VALUES;
        

        【讨论】:

        • 我更喜欢integer(n),可以为n选择合适的值。
        【解决方案6】:

        是语法错误,因为你没有写括号

        如果你写

        选择日期时间('现在') 那么它会给你UTC时间但是如果你写它查询那么你必须在这之前添加括号 所以 (datetime('now')) 表示 UTC 时间。 当地时间相同 选择日期时间('现在','本地时间') 用于查询

        (日期时间('now','localtime'))

        【讨论】:

          【解决方案7】:

          如果你想要毫秒精度,试试这个:

          CREATE TABLE my_table (
              timestamp DATETIME DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
          );
          

          不过,这会将时间戳保存为文本。

          【讨论】:

            【解决方案8】:

            此替代示例将本地时间存储为整数以保存 20 个字节。该工作在字段默认值、更新触发器和视图中完成。 strftime 必须使用“%s”(单引号),因为“%s”(双引号)对我抛出了“Not Constant”错误。

            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
            

            【讨论】:

              猜你喜欢
              • 2011-07-16
              • 2013-02-02
              • 2011-08-14
              • 1970-01-01
              • 2019-05-02
              • 1970-01-01
              • 2011-05-13
              • 2012-11-30
              相关资源
              最近更新 更多