【问题标题】:How to use or replace 'WITH RECURSIVE' in a SQLite trigger to update a tree-structured table如何在 SQLite 触发器中使用或替换“WITH RECURSIVE”来更新树结构表
【发布时间】:2020-11-18 16:44:57
【问题描述】:

在 SQLite 中,我有一个名为 layer 的树形结构表,其中包含 (id, ..., parentId) 列。还有一个名为dir 的普通表,列(id, ..., modifiedTime)。情况是:

一旦dir 中的某些行使用新的 modifiedTime 更新,它们的所有父项也应更新。保证 modifiedTime 不递减。

没有触发器,我可以使用这个 sql 来完成它(通过使用 WITH RECURSIVE 子句):

WITH RECURSIVE P(id) AS (
     SELECT parentId FROM layer WHERE id="The Id of Modified Row"
     UNION ALL
     SELECT L.parentId FROM layer AS L, P WHERE L.id=P.id)
UPDATE dir SET modifiedT=CURRENT_TIMESTAMP WHERE id IN P;

但是当我将 sql 放入触发器时,UPDATE 语句出错。看完SQLite offical doc,我明白了The WITH clause cannot be used within a CREATE TRIGGER.

这就是问题

我怎样才能让触发器做我想做的事?

换句话说,如何替换触发器中的“WITH”子句?

【问题讨论】:

    标签: sql sqlite triggers tree-structure


    【解决方案1】:

    您可以按照此思路创建recursive trigger(可作为 SQLite 3.6.18 使用)。

    CREATE TRIGGER tr_update_parent_modifiedT
    AFTER UPDATE OF modifiedT ON layer
    BEGIN
      UPDATE
        layer
      SET
        modifiedT = (SELECT modifiedT FROM NEW WHERE id = layer.id)
      WHERE
        id IN (SELECT parentId FROM NEW);
    END;
    

    此触发器仅对 modifiedT 的更改做出反应,并将其值复制到父行。相关子查询语法是必要的,因为NEW 总是可以包含多条记录。

    CREATE TRIGGER tr_update_self_modifiedT
    AFTER UPDATE OF parentId, name, all, other, columns, except_modifiedT ON layer
    BEGIN
      UPDATE
        layer
      SET
        modifiedT = CURRENT_TIMESTAMP
      WHERE
        id IN (SELECT id FROM NEW);
    END;
    

    此触发器对任何列上的更改做出反应除了 modifiedT 并设置当前时间戳。结合起来应该可以达到想要的效果。

    您应该再创建两个覆盖INSERTDELETE 的触发器并设置父级modifiedT,否则添加/删除子级不会反映在父级上。

    请注意,必须在连接级别启用递归触发器:

    PRAGMA recursive_triggers = ON;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-02-23
      • 2022-11-17
      • 1970-01-01
      • 2011-10-25
      • 2021-08-25
      • 1970-01-01
      • 2016-05-17
      • 1970-01-01
      相关资源
      最近更新 更多