2012-10-13 34 views
15

这里就是我想要做的事:MySQL的 - 触发用于插入后更新同桌

当有一个新的INSERT到表ACCOUNTS,我需要通过设置status='E'更新的行中ACCOUNTS其中pk = NEW.edit_on表示特定(旧)帐户已被编辑。

DELIMITER $$ 

DROP TRIGGER IF EXISTS `setEditStatus`$$ 
CREATE TRIGGER `setEditStatus` AFTER INSERT on ACCOUNTS 
FOR EACH ROW BEGIN 
    update ACCOUNTS set status='E' where ACCOUNTS.pk = NEW.edit_on ; 
END$$ 

DELIMITER ; 

的要求是不我操纵新插入列,但一个已有pk = NEW.edit_on

但是,我不能更新同一表:Can't update table ACCOUNTS ... already used by the statement that invoked this trigger

请建议一种解决方法

PS:我有一个已经通过Updating table in trigger after update on the same table,Insert into same table trigger mysql,Update with after insert trigger on same tablemysql trigger with insert and update after insert on table,但他们似乎不回答我的问题。

编辑

ACCOUNTS表:

CREATE TABLE `ACCOUNTS` (
    `pk` bigint(10) unsigned NOT NULL AUTO_INCREMENT, 
    `user_id` bigint(9) unsigned NOT NULL, 
    `edit_on` bigint(10) unsigned DEFAULT NULL, 
    `status` varchar(1) NOT NULL DEFAULT 'A', 
    PRIMARY KEY (`pk`) USING BTREE) ENGINE=InnoDB AUTO_INCREMENT=2147483726 DEFAULT CHARSET=latin1 
+0

如何唯一标识'ACCOUNTS'中的行?如果'edit_on'是您的主键,那么您如何插入重复项? – pjama

+0

我编辑了这个问题来包含表结构。请参见。 – th3an0maly

+0

如果'edit_on = 123'表示'pk = 456'的行,这意味着'456'是'123'上的编辑。因此,'status'应该更新为''E'''123' – th3an0maly

回答

19

看来你不能做到这一切的触发器。按照documentation

在存储函数或触发器,它不允许修改已被使用(读或写)由调用函数或触发器的语句的表。

this answer,看来你应该:

创建一个存储过程,即插入到/更新目标表,然后更新其他行(S),所有的交易。

使用存储过程,您将手动提交更改(插入和更新)。我没有在MySQL中这样做,但this post看起来是一个很好的例子。

+0

这是否意味着我必须从触发器中调用存储过程? – th3an0maly

+0

不,我相信你将最初的'INSERT'查询移动到存储过程中,并调用proc而不是查询。以下是MySQL的语法:http://dev.mysql.com/doc/refman/5.0/en/call.html – pjama

+0

我在这里有点困惑。你的意思是将原始插入程序移入过程并使用触发器进行更新,或将*整个*逻辑移入存储过程? – th3an0maly

6

有同样的问题,但必须更新与即将进入ID的列,这样就可以使一个更新前应做和AFTER不是之前没有ID,所以我做这一招

DELIMITER $$ 
DROP TRIGGER IF EXISTS `codigo_video`$$ 
CREATE TRIGGER `codigo_video` BEFORE INSERT ON `videos` 
FOR EACH ROW BEGIN 
    DECLARE ultimo_id, proximo_id INT(11); 
    SELECT id INTO ultimo_id FROM videos ORDER BY id DESC LIMIT 1; 
    SET proximo_id = ultimo_id+1; 
    SET NEW.cassette = CONCAT(NEW.cassette, LPAD(proximo_id, 5, '0')); 
END$$ 
DELIMITER ; 
+0

我不得不说,这是解决这个问题的一种非常粗糙的方式,因为它在没有任何条目被添加/删除的前提下进行存储(从而增加MAX(id)+ 1产生的自动增量值)。无论这是我发现完成我需要的唯一解决方案,我觉得我可以在这个前提下进行存款。我试图(从PHP转移到Django)将所有主键从TABLENAME_ID重命名为ID,而不会中断我的应用程序。好东西。 –

5

这是我如何更新插入同一表中的一行

activationCode和email是表USER中的行。 在插入我没有指定activationCode的值,它将通过MySQL即时创建。

用你的mysql用户名和'db_name'用你的db名称改变'username'。

CREATE DEFINER=`username`@`localhost` 
     TRIGGER `db_name`.`user_BEFORE_INSERT` 
     BEFORE INSERT ON `user` 
     FOR EACH ROW 
     BEGIN 
      SET new.activationCode = MD5(new.email); 
     END 
1

在最后一项;这是另一个把戏:

SELECT AUTO_INCREMENT FROM information_schema.tables WHERE table_schema = ... and table_name = ... 
+0

你可以在编辑时解释一下你的答案吗?谢谢。 – Will