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

时间:2014-04-13 20:14:53

标签: sqlite triggers

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

[名称]

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'实际更新的行中列?

2 个答案:

答案 0 :(得分:9)

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

当原始UPDATE语句未更改id列时,新旧id值相同, all 表中的记录,如内部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