Mysql触发器问题(我认为它正在解雇)

时间:2011-04-30 20:30:15

标签: mysql sql triggers

我在mysql数据库上遇到触发器问题。我有一张如下表:

id int not null auto_increment (PK)
parent_id int not null,
rank int not null

我想要做的是使用触发器将等级更新为具有相同parent_id的下一个最高+10,但这似乎不起作用。

DELIMITER $$
DROP TRIGGER IF EXISTS after_insert $$
create trigger after_insert 
after insert on mytable
FOR EACH row
BEGIN

  IF EXISTS (SELECT rank FROM mytable WHERE parent_id = new.parent_id AND id != new.id ORDER BY rank DESC LIMIT 1) THEN
  UPDATE mytable SET rank  = 10
  WHERE id = new.id;
  ELSE
  UPDATE mytable SET rank = 20
  WHERE id = new.id;
  END IF;   

END
$$

我已经尝试将新排名设置为变量并使用该变量调用更新语句,并且它再次无效。我甚至创建了另一个表来记录正在选择的值和完美的工作,所以我不太明白发生了什么。这是一个案例,虽然触发器是“AFTER INSERT”,插件实际上并没有发生,因此无法更新它刚刚插入的行?我问这个问题的另一个原因是,我甚至尝试将等级更新为不同的值,例如1和2,具体取决于它所使用的语句,但它总是最终为0。

2 个答案:

答案 0 :(得分:2)

我认为你的想法是正确的:

  

是否是这种情况,虽然触发器是“AFTER INSERT”但插件实际上并没有发生,因此无法更新刚刚插入的行?

来自FAQ

  

B.5.9:可以触发访问表吗?

     

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

文档不清楚你正在做的事情是行不通的。 OTOH,文档并不清楚你要做的事情也可以。

我认为您最好使用BEFORE INSERT触发器并在其中设置NEW.rank。然后,当新行实际插入表中而不是之后修补时,新行将具有正确的rank值。此外,您还可以将存在检查简化为:

EXISTS(SELECT rank FROM mytable WHERE parent_id = new.parent_id)

因为NEW.id没有有用的值,所以新行不会在表格中; ORDER BYLIMIT也是不必要的,因为您只是检查是否存在某些内容,因此我将其取出。

BEFORE INSERT触发器似乎更好地符合您的意图,并且只要将其插入您的表格就会立即为您提供正确的数据。

答案 1 :(得分:1)

如果你希望将排名设置为比最高“兄弟”等级多+10,你可以使用:

DELIMITER $$
DROP TRIGGER IF EXISTS whatever $$
create trigger whatever
BEFORE INSERT ON mytable
FOR EACH row
BEGIN

  SET NEW.rank = 10 + COALESCE( 
      ( SELECT max(rank)
        FROM mytable
        WHERE parent_id = NEW.parent_id
      ), 0 ) ;   

END
$$