使用SQLite更新当前时间戳时

e1xvtsh3  于 2023-02-19  发布在  SQLite
关注(0)|答案(5)|浏览(654)

我想在更新行时用当前时间戳更新字段。
在MySQL中,当声明表时,我会这样做

LastUpdate TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP

但是“更新”部分不适用于SQLite。我找不到自动执行的方法,我需要声明触发器吗?

EDIT:为了记录在案,以下是我当前的触发器:

CREATE TRIGGER [UpdateLastTime]
AFTER UPDATE
ON Package
FOR EACH ROW
BEGIN
UPDATE Package SET LastUpdate = CURRENT_TIMESTAMP WHERE ActionId = old.ActionId;
END

谢谢

sg3maiej

sg3maiej1#

是的,你需要使用一个触发器。(只是检查:你贴出的触发器工作正常吗?乍一看,我觉得还不错。)
MySQL的ON UPDATE CURRENT_TIMESTAMP是一个非常独特的、单一用途的快捷方式。该构造 * 不能 * 类似地用于任何其它值或除TIMESTAMP之外的任何列类型。(注意这个功能是如何在TIMESTAMP type page而不是CREATE TABLE page上定义的,因为这个功能是特定于TIMESTAMP列的,而不是特定于CREATE TABLE语句的。)还值得一提的是,虽然它特定于TIMESTAMP类型,SQLite甚至没有不同的日期/时间类型。
据我所知,没有其他RDBMS提供这种快捷方式来代替使用实际的触发器。从我所读到的,触发器必须用来在MS SQL,SQLite,PostgreSQL和Oracle上完成这一点。

  • 给路人的最后一句话:*

不要把它和与外键约束相关的ON UPDATE子句混淆,这是完全不同的东西,可能所有支持外键约束的RDBMS都有(包括MySQL和SQLite)。

idv4meu8

idv4meu82#

John关于默认SQLite设置的说法是正确的,这个触发器会导致无限循环。为了避免递归,请使用WHEN子句。
即使recursive_triggers设置打开,以下操作也将有效:

PRAGMA recursive_triggers=1;     --- test

CREATE TRIGGER [UpdateLastTime]
    AFTER UPDATE
    ON package
    FOR EACH ROW
    WHEN NEW.LastUpdate < OLD.LastUpdate    --- this avoid infinite loop
BEGIN
    UPDATE Package SET LastUpdate=CURRENT_TIMESTAMP WHERE ActionId=OLD.ActionId;
END;
e5nqia27

e5nqia273#

有更有效、更好、更干净的方法来做这件事,例如:

-- List all required fields after 'OF' except the LastUpdate field to prevent infinite loop
CREATE TRIGGER UpdateLastTime UPDATE OF field1, field2, fieldN ON Package
BEGIN
  UPDATE Package SET LastUpdate=CURRENT_TIMESTAMP WHERE ActionId=ActionId;
END;

像这样的代码已经在我的项目中测试过了。深sqlite触发器解释可以在这里找到https://www.sqlite.org/lang_createtrigger.html

mlnl4t2r

mlnl4t2r4#

这是一个旧的,但我遇到了这个当试图自动更新SQLite像所有。建议的解决方案有帮助,但仍然需要修复。这里是:

CREATE TRIGGER [UPDATE_DT]
    AFTER UPDATE ON table_name FOR EACH ROW
    WHEN OLD.field_name = NEW.field_name OR OLD.field_name IS NULL
BEGIN
    UPDATE table_name SET field_name=CURRENT_TIMESTAMP WHERE unique_field=NEW.unique_field;
END;
    • 解释:**
  • OLDNEW是服务器使用的"临时"示例,位于存储的(旧)数据和要更新的(新)数据之间
  • WHEN必须与=进行比较,以便在更新除updated_field_name值之外的所有数据时运行...并且必须接受字段本身的手动更新,而不会进入无限循环
  • 如果从未设置字段,则还需要发生WHEN,因此需要IS NULL子句,因为=是不够的
  • 一旦触发器是AFTER UPDATE,则WHERE需要从NEW唯一或主键找到更新的注册表,因为甚至键也可以被更新;-)
xoefb8l8

xoefb8l85#

-- Describe UPDATELASTTIME  
CREATE TRIGGER [UpdateLastTime]  
    AFTER   
    UPDATE  
    ON test
    FOR EACH ROW   
    WHEN NEW.last_update_ts <= OLD.last_update_ts  
BEGIN  
    update test set last_update_ts=CURRENT_TIMESTAMP where id=OLD.id;  
END  

-- Describe TEST  
CREATE TABLE "main"."test" (  
    "id" INTEGER PRIMARY KEY AUTOINCREMENT,  
    "name" TEXT,  
    "last_update_ts" DATETIME DEFAULT CURRENT_TIMESTAMP  
);

相关问题