我在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。
答案 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 BY
和LIMIT
也是不必要的,因为您只是检查是否存在某些内容,因此我将其取出。
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
$$