我正在尝试在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
但这有问题。每次在此表的记录上发生更新时,触发器都会在同一记录上触发新的更新。这应该再次触发触发,并再次导致无限循环的更新。
这真的会发生什么?触发器中的更新是否会再次触发触发器? 我可以避免在触发器内触发触发器吗?
答案 0 :(得分:2)
实际上,我们在谈论SQLite,是吗?最初,不支持递归触发器(上面怀疑的无限循环)以防止出现此问题。它们现在受支持,但默认情况下已关闭。理论上,您可以使用"PRAGMA recursive-triggers = true"
将其重新打开。
马的嘴在这里:SQLite Online Doc
答案 1 :(得分:1)
使用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
子句。
答案 2 :(得分:0)
对于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;
答案 3 :(得分:0)
John,使用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的网页上使用(方法。