问题:最简单的更新触发器会将新值写入所有表行,而不仅仅是正在更新的行。这是表格:
[名称]
id INTEGER PRIMARY KEY
name TEXT
len INTEGER
现在我想创建触发器来更新' len'长度为' name'。这个INSERT触发器似乎正在做核心工作:
CREATE TRIGGER 'namelen' AFTER INSERT ON 'names'
BEGIN
UPDATE 'names' SET len = length(NEW.name) WHERE (id=NEW.id);
END;
当我添加类似的UPDATE触发器时,问题就开始了:
CREATE TRIGGER 'namelenupd' AFTER UPDATE ON 'names'
BEGIN
UPDATE 'names' SET len = length(NEW.name) WHERE (OLD.id=NEW.id);
END;
更新触发器将新长度写入表的所有行,尽管有WHERE子句。例如,如果我说
UPDATE 'names' SET name='foo' where id=1;
然后是' len'的价值。对于表格的所有行,它变为3。我查看过sqlite触发器示例,但我看不到自己的错误。我还必须做些什么来确保触发器更新' len'实际更新的行中仅列?
答案 0 :(得分:9)
OLD.xxx和NEW.xxx都引用导致触发器运行的表行。
触发器内的UPDATE语句独立运行;如果要将其限制为一个表行,则必须通过对 语句的表值进行过滤来明确地在其WHERE子句中执行此操作,即names.id
或仅id
当原始UPDATE语句未更改id
列时,新旧id
值相同, all 1}}表达式为真表中的记录,如内部UPDATE语句所示。
正确的触发器如下所示:
OLD.id=NEW.id
答案 1 :(得分:0)
有同样的问题,这里是我的触发器的语法
你会改变" ALTER"到"创建"取决于你已经拥有(或不拥有)
您有"id"
作为主键
您的dbo是"names"
显然,这会将名称值设置为" foo" (不是你真正想要的)。密钥似乎是最后一行,您设置inner join inserted on names.Id = inserted.Id
。
USE [yourDBname]
ALTER TRIGGER [dbo].[yourTrigger]
ON [dbo].[names]
After INSERT, UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
Select id from inserted
begin
update [dbo].names
set [dbo].names.name = 'foo'
from dbo.names
inner join inserted
on names.id = inserted.id
END