创建表列时如何正确使用 ON UPDATE CURRENT_TIMESTAMP?

Posted

技术标签:

【中文标题】创建表列时如何正确使用 ON UPDATE CURRENT_TIMESTAMP?【英文标题】:How do I properly use ON UPDATE CURRENT_TIMESTAMP when creating table column? 【发布时间】:2020-05-12 22:27:28 【问题描述】:

我是 SQL 的新手,我看到在创建包含列的表时,只要更新列(这正是我想要的),我就可以自动将列更新为当前时间戳,具体如下:

CREATE TABLE IF NOT EXISTS Foo (
  Symbol CHAR(5),
  LastUpdated DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)

所以,根据我的理解,当我在这个表中插入一个符号时,例如'Baz',它应该在表中创建以下条目:

|---------------------|------------------|
|        Symbol       |    LastUpdated   |
|---------------------|------------------|
|         Baz         |  <current time>  |
|---------------------|------------------|

如果我将符号从“Baz”更新为“Qux”,则该行的 LastUpdated 列应更改为新的当前日期时间。但是,当我使用 sqlite3 模块在 python 中运行该查询时,出现以下错误:sqlite3.OperationalError: near "ON": syntax error。这是代码在 Python 中的样子:

self.__conn = sqlite3.connect(database_path)
self.__cursor = self.__conn.cursor()
self.__cursor.execute("""CREATE TABLE IF NOT EXISTS EQData (
                         Symbol CHAR(5),
                         LastUpdated DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP)""")

我尝试过稍微弄乱该列定义,我发现如果我删除 ON UPDATE CURRENT_TIMESTAMP 部分,所以它只是 LastUpdated DATETIME DEFAULT CURRENT_TIMESTAMP 查询将执行得很好,但问题是我仍然希望它每当更新该行时自动更新其 LastUpdated 列。我看到here 我可以使用某种代码,该代码看起来像是触发了一个事件,当我的行更新时将更新列,但我不确定它为什么起作用或为什么我应该在我想工作的一段代码。理想情况下,我希望ON UPDATE CURRENT_TIMESTAMP 部分能够以某种方式工作,而不是在另一个 *** 问题上添加该用户提供的代码。

所以我真的有两个问题:

    为什么我收到关于 ON UPDATE 部分的错误,尽管它是从源复制/粘贴的? 如何正确获取行以在更新行时自动更新其 LastUpdated 列?

【问题讨论】:

【参考方案1】:

不幸的是,与 mysql 不同,SQLite 不支持 ON UPDATE CURRENT_TIMESTAMP 语法(我不确定 MySQL 是否真正提供该功能的任何其他数据库)。

解决此问题的一种方法是使用触发器。假设你的表的主键是id,那就是:

CREATE TRIGGER Trg_LastUpdated
AFTER UPDATE ON Foo
FOR EACH ROW
BEGIN
    UPDATE Foo SET LastUpdated = CURRENT_TIMESTAMP WHERE id = OLD.id;
END

Demo on DB Fiddle

【讨论】:

感谢您的快速响应,有什么方法可以检查我是否已经创建了这个触发器,所以我不会继续将它重新添加到我的数据库中?或者这是我不必担心的事情?我担心的是,如果多次执行此语句,它将创建重复的触发器,这些触发器都执行相同的操作,我假设这会产生性能问题。另一个问题是,您的 SQL 语句会更新所有行上的 LastUpdated 列还是只更新已更改的行? @DomStepek:(1) 您可以查询目录视图sqlite_master 以列出所有现有触发器,例如select * from sqlite_master where type = 'trigger';。 (2) 这只会更新刚刚更新的行(前提是您有一个主键,如我的回答中所述)。

以上是关于创建表列时如何正确使用 ON UPDATE CURRENT_TIMESTAMP?的主要内容,如果未能解决你的问题,请参考以下文章

Oracle GoldenGate 生成表列时始终标识类型_IT 不允许在目标数据库表中插入

Derby Trigger on UPDATE:如何更新时间戳?

通配符表和表列中的差异

如何使用 sqlalchemy 在 mysql 中设置 DEFAULT ON UPDATE CURRENT_TIMESTAMP?

如何按特定顺序进行 SQL UPDATE

#1293 - 表定义不正确;在 DEFAULT 或 ON UPDATE 子句中只能有一个带有 CURRENT_TIMESTAMP 的 TIMESTAMP 列