2009-09-30 16 views
2

我使用mysql5.1并在update.am中使用同样的表插入和更新后写入触发器。 表包含字段.ID,商品ID,值1都是整数..在同一个表中的mysql触发器

我的触发是:

CREATE DEFINER = 'root'@'%' TRIGGER `trig_same` 
    AFTER UPDATE 
    ON `vote` 
    FOR EACH ROW 
BEGIN 
    insert into vote values(10,1,100); 
END| 

...但是当我EXCUTE更新命令我得到的错误:

SQL Error: Can't update table 'vote' in stored function/trigger because it is already used by statement which invoked this stored function/trigger. 

回答

1

按照定义,触发器创建一个循环参考。它插入另一行,然后需要再次调用触发器,再插入另一行,这会导致它再次被调用....

如果SQL没有捕获到这个表,最终会被这些(10,1,100)记录填满,因此不会耗尽数据库或硬盘上的空间。

我假设你只希望为每个'正常'记录插入添加一个addtional记录。这可以通过修改执行插入操作的逻辑来实现(如果可能,在该级别添加第二个INSERT)。
编辑 [2011年4月17日]:正如约翰指出的那样,下面的“装置”会失败并出现同样的错误。我并不担心修复它,因为相当奇怪的底层用例...
另一种方法是在INSERT触发器之后使用自己的独立表;投票表的触发器将需要测试(10,1,100)值,并在这种情况下返回(除此之外别无其他),否则将在另一个表上插入一条记录;这个其他表将会有触发器在表'vote'上插入这个记录。 (相当做作对于相对奇数用例!)

+0

当我使用相同的表的所有触发操作我得到这个错误。 – maxy 2009-09-30 06:09:05

+0

@maxy,对,我意识到这一点。这是我在我的回答中试图解释的;你不能有一个直接的循环引用,并且,你需要打破递归... – mjv 2009-09-30 06:28:21

+0

我怎么能打破这..有任何其他的解决方案.. – maxy 2009-09-30 06:58:07

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)只能执行某些 语句。一旦你得到这个想法,你可以使用一个简单的方法;)

+0

我检查了你的解决方案,它不起作用或 可以请你解释更多,并提供更具体的源代码? – Marecky 2013-02-08 16:26:50

+0

这是我在触发器中使用的所有代码,可能是您可以将所有代码发布到某处(pastbin?),我可以检查它。你需要记住,这个解决方案不能提供完美的解决方案。您可以使用简单的异常/错误处理程序来处理循环引用问题,这样只要您拥有它们,您就可以简单地从触发器中退出 – sakhunzai 2013-02-11 05:57:58

相关问题