MySQL触发器:在UPDATE,删除旧行(如果存在)并取消更新

时间:2014-03-11 08:30:12

标签: mysql triggers

我有一张桌子,我想在其中执行UPDATE。我的问题是更新更改主键并可能因碰撞而产生错误,例如:我想更新密钥从1-15更新到1-16,并且存在1-16,因此出现错误

我知道如何通过PHP实现,但如果没有冲突,我只需要UPDATE,如果发生冲突,我只需DELETE旧行并取消UPDATE。所以我决定使用触发器,因为我觉得它非常干净,例如:如果我想{1}到1-15到1-16,并且存在1-16,则删除1-15并中止UPDATE 。这是我试图创建的触发器:

UPDATE

但是回复了MySQL错误:

CREATE TRIGGER table_trigger BEFORE UPDATE ON table FOR EACH ROW BEGIN IF ( SELECT COUNT(1) FROM table WHERE item_id = NEW.item_id AND related_id = NEW.related_id ) THEN DELETE FROM table WHERE item_id = OLD.item_id AND related_id = OLD.related_id; ROLLBACK TRANSACTION; END IF; END;//

这是DELETE行。我没有太多关于触发器的知识,我怎样才能实现它我正在尝试的东西?我是在正确的方式吗?

1 个答案:

答案 0 :(得分:2)

OP的评论:

  

我使用ROLLBACK TRANSACTION尝试中止更新

根据documentation on Triggers(偶数函数)不能使用显式提交/回滚。这是不允许的。

  

触发器不能使用显式或隐式开始或结束事务的语句,例如START TRANSACTION,COMMIT或ROLLBACK。

如果您不想在条件匹配时执行update,最好抛出错误。它不会让更新发生。

示例

delimiter //

drop trigger if exists table_trigger //

CREATE TRIGGER table_trigger BEFORE UPDATE ON table
FOR EACH ROW
BEGIN
  declare rowCount int default 0;
  declare error_message varchar(1024) default '';

  SELECT COUNT(1) into rowCount FROM table 
  WHERE item_id = NEW.item_id 
    AND related_id = NEW.related_id ;

  IF ( rowCount > 0 ) THEN -- if( rowCount ) -- too works
    -- DELETE FROM table 
    --   WHERE item_id = OLD.item_id 
    --     AND related_id = OLD.related_id;
    -- ROLLBACK TRANSACTION; -- this is not allowed

    set error_message = 
        concat( error_message, 'Update not allowed for ' );
    set error_message = 
        concat( error_message, 'combination \'item_id=' );
    set error_message = 
        concat( error_message, NEW.item_id, '\' and ');
    set error_message = 
        concat( error_message, '\'related_id=', NEW.related_id, '\'' );

    -- throw the error
    -- Update not allowed for combination 
    -- 'itemid=1' and 'related_id=5'  ( example )
    signal sqlstate 23000 set message_text = error_message;
  END IF;
END;//

delimiter ;