【问题标题】:Do sqlite triggers trigger other triggers?sqlite 触发器会触发其他触发器吗?
【发布时间】:2014-01-19 22:21:13
【问题描述】:

我正在尝试在 sqlite 中实现相当于“ON UPDATE CURRENT_TIMESTAMP”MySQL 功能。 我的想法是使用这样的触发器:

CREATE TRIGGER last_update_trigger
AFTER UPDATE
ON mytable
FOR EACH ROW
BEGIN
UPDATE mytable SET last_update = CURRENT_TIMESTAMP WHERE id = old.id;
END

但这有一个问题。每次在该表的记录上发生更新时,触发器都会在同一记录上触发新的更新。这应该会一次又一次地触发触发器,从而导致无限循环的更新。

这真的会发生吗?我的触发器中的更新会再次触发触发器吗? 是否可以避免触发触发器内的触发器?

【问题讨论】:

    标签: sqlite triggers timestamp sql-update


    【解决方案1】:

    我们说的是 SQLite,对吧?

    最初,专门支持递归触发器(上面怀疑的无限循环)以防止此问题。它们现在受支持,但默认关闭。 in theory,您可以使用

    重新打开它们
    PRAGMA recursive_triggers = ON;
    

    【讨论】:

      【解决方案2】:

      使用before update 触发器:

      CREATE TRIGGER last_update_trigger
      BEFORE UPDATE
      ON mytable
      FOR EACH ROW
      BEGIN
          set new.last_update = CURRENT_TIMESTAMP;
      END;
      

      或者,更好的是,使用默认值。

      编辑:

      在 SQLite 中,您可以使用 instead of 触发器而不是之前的触发器来执行此操作。比如:

      CREATE TRIGGER last_update_trigger
      INSTEAD OF UPDATE
      ON mytable
      FOR EACH ROW
      BEGIN
          update mytable
              set last_update = CURRENT_TIMESTAMP,
                  col1 = new.col1,
                  col2 = new.col2,
                  . . .
      END;
      

      但是,我认为更好的选择是表定义中的default 子句。

      【讨论】:

      • 看起来这在语法上不正确。根据sqlite.org/lang_createtrigger.html 的文档,我需要在 BEGIN 和 END 之间有一个 UPDATE 语句。这应该会导致我在原始帖子中描述的相同问题:无限循环。触发循环的实际原始更新永远不会发生。
      • 问题标记为 MySQL,这是 MySQL 允许的语法 (dev.mysql.com/doc/refman/5.7/en/create-trigger.html)。 SQLite 语法可能有些不同。
      • 对不起,我试图用 sqlite 模拟 MySQL 功能。我不需要 MySQL 解决方案,因为 MySQL 已经使用简单的ON UPDATE CURRENT_TIMESTAMP 语句来完成此操作。我要删除mysql标签,因为它很混乱。
      • @GordonLinoff INSTEAD OF 触发器不允许在表上使用。
      • @CL。 . . .不知何故,SQLite 使这比它应该做的要困难得多。您可以创建一个视图并对视图进行更新。我希望其他人能提供更好的答案。
      【解决方案3】:

      对于 UPDATE 触发器,您可以指定它应该在哪些列上触发。 只需将 last_update 列从该列表中删除即可:

      CREATE TRIGGER MyTable_last_update
      AFTER UPDATE OF col1, col2, etc ON MyTable
      FOR EACH ROW
      BEGIN
          UPDATE MyTable
          SET last_update = CURRENT_TIMESTAMP
          WHERE id = OLD.id;
      END;
      

      【讨论】:

      • 是的,我考虑过这一点,但我希望能够向表中添加列,并且触发器仍然适用于更新新列。
      【解决方案4】:

      约翰,使用 WHEN 子句,即使启用递归触发器也能正常工作。

      PRAGMA recursive_triggers=1;
      CREATE TRIGGER IF NOT EXISTS "mytable_last_update"
          AFTER UPDATE ON main.mytable FOR EACH ROW
          WHEN NEW.last_update < OLD.last_update
      BEGIN
          UPDATE mytable SET last_update=CURRENT_TIMESTAMP WHERE oid=OLD.oid;
      END;
      

      我使用 (strftime('%s','now')||substr(strftime('%f','now'),4)) 代替 CURRENT_TIMESTAMP,用于在带有 Javascript Date( ) 方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-11
        • 1970-01-01
        • 1970-01-01
        • 2019-08-07
        • 2010-11-14
        • 1970-01-01
        相关资源
        最近更新 更多