SQLite3更新触发器触发所有行,忽略WHEN和/或WHERE条件

时间:2014-05-26 16:13:55

标签: sqlite

我尝试向Sqlite3中的表添加UPDATE触发器,并且触发器会更新所有行,尽管我努力将其限制为仅实际更改的行。简单的化妆示例表:

CREATE TABLE IF NOT EXISTS prices (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    base REAL DEFAULT 100.0,
    discount REAL DEFAULT 0.0,
    actual REAL DEFAULT 0.0
);
INSERT INTO prices(base,discount,actual) VALUES (100,0,100),(200,0,200),(300,0,300);

应使用以下触发器更新实际价格:

CREATE TRIGGER "upd" AFTER UPDATE OF discount ON prices FOR EACH ROW
WHEN (OLD.discount <> NEW.discount)
BEGIN
    UPDATE prices SET actual = base * (1-NEW.discount/100.0)
    WHERE OLD.discount <> NEW.discount;
END;

如果我改变那么就说第二行:

UPDATE prices SET discount = 50 WHERE rowid = 2;

然后触发器在所有行上触发,不仅在第二行触发,并且所有行中的“实际”字段将乘以0.5。

正如您所看到的,触发器带有一个腰带和一个吊带:WHEN子句和WHERE子句都试图确保只有那些折扣值发生变化的行受到影响。通过指定/或WHEN,WHERE等来尝试所有4种组合无济于事。以下是UPDATE

之后的表格内容
1|100.0|0.0|50.0
2|200.0|50.0|100.0
3|300.0|0.0|150.0

请注意,有一个看似相关的SO question,但OP使用了以下子句:WHERE (OLD.id=NEW.id)对于所有未更改的行当然是TRUE,所以难怪它不起作用正如所料。我担心那里提供的解决方案不适用于我的情况。任何帮助将不胜感激。

编辑:CL之后。这里的-s解释是正确的触发器:

CREATE TRIGGER "upd" AFTER UPDATE OF discount ON prices FOR EACH ROW
BEGIN
    UPDATE prices SET actual = base * (1-NEW.discount/100.0)
    WHERE id = NEW.id; -- this selects the row that fired the trigger!
END;

0 个答案:

没有答案