SQLite更新触发器更改表中的所有行

Mar*_*ski 7 sqlite triggers

问题:最简单的更新触发器会将新值写入所有表行,而不仅仅是正在更新的行.这是表格:

[名]

id INTEGER PRIMARY KEY
name TEXT
len INTEGER
Run Code Online (Sandbox Code Playgroud)

现在我想创建触发器以'name'的长度更新'len'.这个INSERT触发器似乎正在做核心工作:

CREATE TRIGGER 'namelen' AFTER INSERT ON 'names'
BEGIN
UPDATE 'names' SET len = length(NEW.name) WHERE (id=NEW.id);
END;
Run Code Online (Sandbox Code Playgroud)

添加类似的UPDATE触发器时出现问题:

CREATE TRIGGER 'namelenupd' AFTER UPDATE ON 'names'
BEGIN
UPDATE 'names' SET len = length(NEW.name) WHERE (OLD.id=NEW.id);
END;
Run Code Online (Sandbox Code Playgroud)

尽管有WHERE子句,update触发器会将新长度写入表的所有行.例如,如果我说

UPDATE 'names' SET name='foo' where id=1;
Run Code Online (Sandbox Code Playgroud)

然后'len'的值对于表的所有行变为3 .我看过sqlite触发器示例,我看不到我的错误.还有什么办法可以确保触发器在实际更新的行中更新'len'列?

CL.*_*CL. 10

OLD.xxx和NEW.xxx都引用导致触发器运行的表行.触发器内的UPDATE语句独立运行; 如果要将其限制为一个表行,则必须通过对该语句的表值进行过滤来明确地在其WHERE子句中执行此操作,即,names.id或者只是id.

当原始UPDATE语句不更改id列时,旧id值和新值相同,表达式OLD.id=NEW.id对于表中的所有记录为true ,如内部UPDATE语句所示.

正确的触发器如下所示:

CREATE TRIGGER "namelenupd"
AFTER UPDATE OF name ON "names"
BEGIN
    UPDATE "names" SET len = length(NEW.name) WHERE id = NEW.id;
END;
Run Code Online (Sandbox Code Playgroud)