MySQL BEFORE INSERT触发器将重复的主键插入更新

时间:2017-09-13 21:03:54

标签: mysql sql triggers phpmyadmin sql-insert

我正在尝试通过 phpmyadmin

在数据库中执行此查询
create trigger avoid_duplicated_sharing
before insert on sharingevents
for each row
begin
  if ( select count(*) from sharingevents where shared_note_id = NEW.shared_note_id AND shared_to = NEW.shared_to  > 0 ) then
      delete from sharingevents where shared_note_id = NEW.shared_note AND shared_to = NEW.shared_to
  END IF;
END

但是 phpmyadmin 给了我以下错误:

MySQL said: #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'END IF' at line 7

两个问题:

  • 我的剧本出了什么问题?
  • BEFORE INSERT触发后,是否会执行INSERT操作?如果不是,我将不得不删除INSERT INTO SharingEvents (SELECT * FROM NEW);

3 个答案:

答案 0 :(得分:0)

使用exists

if (exists (select 1 from sharingevents where shared_note_id = new.shared_note_id AND shared_to = new.shared_to) > 0)  then
    insert into sharingevents (shared_note_id,shared_to,permission_level) 
        values (NEW.shared_note_id,NEW.shared_to,NEW.permission_level);
end if;

或者,更好的是,在sharingevents(shared_note-id, shared_to)上添加唯一索引,然后使用:

    insert into sharingevents (shared_note_id, shared_to, permission_level) 
        values (NEW.shared_note_id, NEW.shared_to, NEW.permission_level)
        on duplicate key update shared_note_id = values(shared_note_id);

这将忽略表中已存在对的任何更新。不需要if

答案 1 :(得分:0)

count(shared_note_id, shared_to)语法无效。使用COUNT()时,只能在count(DISTINCT ...)内添加多个列名称。在您的情况下,您根本不需要放置列名,只需使用COUNT(*)来计算与条件匹配的行数。

有关何时应将列名放在COUNT()

中的详细信息,请参阅count(*) and count(column_name), what's the diff?

不幸的是,修复语法错误并不能真正解决您的问题,因为您无法使用触发器对同一个表进行更改。来自FAQ

  

可以触发访问表吗?
  触发器可以访问其自己的表中的旧数据和新数据。触发器也可以影响其他表,但不允许通过调用函数或触发器的语句修改已经使用(用于读取或写入)的表。

您需要重新编码调用者以使用INSERT ... ON DUPLICATE KEY UPDATE或类似的东西来完成此操作。

答案 2 :(得分:0)

我用以下代码解决了这个问题:

delimiter $$

create trigger avoid_duplicated_sharing
before insert on sharingevents
for each row
begin
    if ( select count(*) from sharingevents where shared_note_id = NEW.shared_note_id AND shared_to = NEW.shared_to  > 0 ) then
        delete from sharingevents where shared_note_id = NEW.shared_note_id AND shared_to = NEW.shared_to;
    end if;
END$$

问题是分隔符。

即便如此,我的触发器也不起作用。当应用程序插入重复的主键时,MySQL会抛出以下错误:

#1442 - Can't update table 'sharingevents' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.