开发者

Mysql trigger issue (i think it's firing)

开发者 https://www.devze.com 2023-03-01 14:56 出处:网络
I have an issue with a trigger on a mysql database. I have a table such as follows: id int not null auto_increment (PK)

I have an issue with a trigger on a mysql database. I have a table such as follows:

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

What I'm trying to do is use a trigger to update the rank to the next highest +10 when they have the same parent_id, but this doesn't seem to be working.

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
$$

I've tried setting the new rank to a variable and calling the update statement using that, and again it didn't work. I even created another table to log what values were being selected and that worked perfectly so I can't quite understand what's going on. Is it a case of, although the trigger is "AFTER INSERT" the insert hasn't actually happened so it can't update the row it's just inserted? Another reason I ask this is, I've even tried updating the rank to different valu开发者_开发百科es e.g 1 and 2 depending on which statement it goes to, but it always ends up being 0.


I think you're on the right track with this thought:

Is it a case of, although the trigger is "AFTER INSERT" the insert hasn't actually happened so it can't update the row it's just inserted?

From the FAQ:

B.5.9: Can triggers access tables?

A trigger can access both old and new data in its own table. A trigger can also affect other tables, but it is not permitted to modify a table that is already being used (for reading or writing) by the statement that invoked the function or trigger.

The documentation isn't clear that what you're doing won't work. OTOH, the documentation isn't clear that what you're trying to do will work either.

I think you'd be better off using a BEFORE INSERT trigger and setting NEW.rank in there. Then, the new row would have the right rank value when it is actually inserted into the table rather than patching it after. Also, you'd be able to simplify your existence check to just this:

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

as NEW.id wouldn't have a useful value and the new row wouldn't be in the table anyway; the ORDER BY and LIMIT are also unnecessary as you're just checking if something exists so I took them out.

A BEFORE INSERT trigger seems to match your intent better anyway and that will give you correct data as soon as it is inserted into your table.


If you want the rank to be set +10 more than highest "brother's" rank, you could use:

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
$$
0

精彩评论

暂无评论...
验证码 换一张
取 消