我正在使用mysql5.1并在update.am之后使用相同的表格对insert和updae编写触发器。 table包含字段.id,itemid,value1 all都是整数..
我的触发器是:
CREATE DEFINER = 'root'@'%' TRIGGER `trig_same`
AFTER UPDATE
ON `vote`
FOR EACH ROW
BEGIN
insert into vote values(10,1,100);
END|
...但是当我执行更新命令时出现错误:
SQL Error: Can't update table 'vote' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
答案 0 :(得分:1)
根据定义,触发器会创建循环引用。它会插入另一行,然后需要再次调用触发器,并插入另一行,这将导致再次调用....
如果SQL没有捕到这个,那么投票表最终将满载这些(10,1,100)个记录,unltil会耗尽数据库或硬盘的空间。
我假设您只希望为每个“正常”记录插入添加一个附加记录。这可以通过修改执行插入本身的逻辑来实现(如果可能的话,在该级别添加第二个INSERT)
编辑 [2011年4月17日]:正如约翰所指出的,以下“装置”会因同样的错误而失败。鉴于相当奇怪的潜在用例,我并不担心修复它......
另一种方法是在INSERT Trigger之后使用一个单独的表;投票表的触发器需要测试(10,1,100)值,并在这种情况下返回(不执行任何操作),否则在另一个表上插入记录;这个其他表将触发器在表'投票'上插入此记录。 (对于一个相对奇怪的用例,我做了很多设计!)
答案 1 :(得分:0)
打破循环引用将需要另一个表,例如:
CREATE TABLE `trigger_semaphore` (
`id` INTEGER(11) NOT NULL,
`semaphore` INTEGER(11) DEFAULT NULL,
`actions` VARCHAR(20) COLLATE utf8_general_ci DEFAULT NULL,
`random` INTEGER(11) DEFAULT NULL,
PRIMARY KEY (`id`)
)ENGINE=MyISAM
CHARACTER SET 'latin1' COLLATE 'latin1_swedish_ci';
CREATE DEFINER = 'root'@'localhost' TRIGGER `trigger_semaphore_before_upd_tr`
BEFORE UPDATE ON `trigger_semaphore`
FOR EACH ROW
BEGIN
DECLARE semaphore int;
set New.random=RAND()*1000;
if New.actions='++' then
set New.semaphore=COALESCE(New.semaphore,0)+1;
elseif New.actions='--' then
set semaphore= COALESCE(New.semaphore,0);
if semaphore<=0 then
set New.semaphore=semaphore;
else
set New.semaphore=semaphore-1;
end if;
end if;
END;
在相互更新的表的触发器中使用trigger_semaphore表 这样:
update trigger_semaphore set actions='++' where id=1;
select semaphore into _semaphore from trigger_semaphore where id=1;
if _semaphore=1 then
# ...... Here goes the code without circular reference..........
end if;
现在在触发器
结束时释放信号量 update trigger_semaphore set actions='--' where id=1;
简而言之,首先设置信号量(1)的表只能执行某些信号 声明。一旦你明白了,你就可以使用一种简单的方法;)