更新后的SQLite触发器

时间:2017-09-24 10:34:40

标签: sqlite

我的表有时间戳列。我想要一个触发器,当更新行并且在update语句中没有指定时间戳时,在受影响的行上将时间戳设置为0。

如果我使用此触发器:

CREATE TRIGGER AFTER UPDATE ON mytable FOR EACH ROW
WHEN (NEW.timestamp IS NULL)
BEGIN
UPDATE mytable SET timestamp = 0 WHERE id = NEW.id;
END;

然后触发器不会触发此更新语句:

UPDATE mytable SET comecolumn='some'

即。受影响的行的时间戳不会更改为0.

你能帮我定一下触发器吗?

3 个答案:

答案 0 :(得分:2)

对UPDATE触发器中的行进行其他更改的唯一方法是在之后的同一个表上执行另一个UPDATE。

检测列值是否更改的唯一方法是比较旧行值和新行值;触发器不知道原始UPDATE语句中实际提到了哪些列。

为防止触发器以递归方式触发,您应该将其限制为由除时间戳之外的所有列的更改触发:

CREATE TRIGGER clear_timestamp
AFTER UPDATE OF all_the, other, columns ON MyTable
FOR EACH ROW
WHEN OLD.timestamp = NEW.timestamp
BEGIN
    UPDATE MyTable
    SET timestamp = 0
    WHERE id = NEW.id;
END;

答案 1 :(得分:0)

我认为问题在于SET语句扩展到每一列,每列都设置为数据库中的当前值。因此,如果当前timestamp列为NULL,则原始唯一触发器有效。

解决方案可能是创建另一个触发器,在NULL之前将时间戳列重置为UPDATE

CREATE TRIGGER "set_null"
BEFORE UPDATE ON "mytable" FOR EACH ROW 
BEGIN
UPDATE mytable set timestamp = NULL where rowid = NEW.rowid;
END

如果NEW.timestamp中未指定NULL,则UPDATE SETNOT NULL

显然现在无法在时间戳上设置PRAGMA recursive_triggers = OFF; 约束。

另一个问题是执行更新查询时必须关闭触发器递归:

let inputSequence = 
      ["a"; "b"; "c";
       "a"; "b"; "c"; "d";
       "a"; "b"; 
       "a"; "d"; "f";
       "a"; "x"; "y"; "z"]

let desiredResult = 
   [["a"; "b"; "c";]
    ["a"; "b"; "c"; "d";]
    ["a"; "b"; ]
    ["a"; "d"; "f";]
    ["a"; "x"; "y"; "z"]]

答案 2 :(得分:0)

这是另一种方式:

import sqlite3
conn = sqlite3.connect(':memory:')
c = conn.cursor()
name = {'name':'jack'}

c.execute("""CREATE TABLE Programs (
    id INTEGER PRIMARY KEY,
    name VARCHAR(64) NOT NULL,
    time_added INTEGER
);""")

c.execute("""CREATE TRIGGER program_time_added AFTER INSERT ON Programs
    FOR EACH ROW
    BEGIN
        UPDATE Programs SET time_added =datetime('now', 'localtime') WHERE id = NEW.id;
    END;""")

c.execute('INSERT INTO Programs (name) VALUES (?)', [name['name']])