2011-08-03 58 views
1

我正在制作一个相当简单的票务管理系统。我想保留一个日志,以获取添加,删除和更改的内容。MySQL UPDATE触发器:插入实际更改的列的值

我创建了三个触发器,AFTER INSERTAFTER DELETEAFTER UPDATEINSERT/DELETE触发器很简单,它是我遇到问题的UPDATE触发器。

我想补充这列已经改变了在表中的旧&新值,即colname changed from X to Y

触发我现在有“作品”,当然除了它不插入实际值我想要。

如何使用col_name变量从OLDNEW获取值?

我也不知道这是做这个的最好可能方式......所以,如果任何人有这想法,他们是欢迎太...这个触发器开始了简单了很多。 ..

BEGIN 
    DECLARE num_rows, i int default 1; 
    DECLARE col_name CHAR(255); 
    DECLARE updated TEXT; 

    DECLARE col_names CURSOR FOR 
     SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS 
     WHERE table_name = 'storing' 
     ORDER BY ordinal_position; 

    OPEN col_names; 
    SELECT FOUND_ROWS() INTO num_rows; 
    SET i = 1; 
    SET @updated = 'Updated columns: '; 

    the_loop: LOOP 
     IF i > num_rows THEN 
      LEAVE the_loop; 
     END IF; 

     FETCH col_names INTO col_name; 

     /* So, how do I get the proper values? */ 
     /* IF [email protected]_name != [email protected]_name THEN */ 
     /*SET @updated = CONCAT(@updated, [email protected]_name, ' changed into ', [email protected]_name, ' ');*/ 
     SET @updated = CONCAT(@updated, 'OLD', ' changed into ', 'NEW', ' '); 
     /* END IF;*/ 

     SET i = i + 1; 
    END LOOP the_loop; 

    CLOSE col_names; 

    INSERT INTO `log` (`storing`, `medewerker`, `actie`, `data`) 
    VALUES (NEW.`id`, NEW.`medewerker`, "Storing aangepast", @updated); 
END 

回答

1
  1. 由于编写,J的使用这里的红色语句是不可能的,我建议你调用一些INSERT语句,例如 -

    如果NEW.column1 <> OLD.column1 THEN INSERT INTO ... END IF; IF NEW.column2 <> OLD.column2 THEN INSERT INTO ... END IF; ...

  2. 或尝试将需要的所有字段复制到另一个表中。

在这些情况下,您将避免使用游标。

+0

谢谢,这个工程,我实现它(第一个)作为一个临时解决方案,但说实话,它并不真正非常漂亮......我宁愿循环的列名... – Carpetsmoker

+0

所以我去了这个结束。它看起来可能不是特别漂亮,但我认为列不会改变那么多,而且它更简单很多(比较少出错,对未来的维护人员不太了解等)。 – Carpetsmoker

0

尝试使用prepared statements 事情是这样的:

SET @s = CONCAT('SELECT new.', @col_name, ', old.', @col_name, ' FROM ', /*here is the query details like inner joins etc.*/, ' where ', 'NEW.', @col_name, '!= OLD.', @col_name) 
    PREPARE stmt FROM @s; 
    EXECUTE stmt; 
+2

从参考 - 准备语句的SQL语法可以在存储过程中使用,但不能在存储函数或触发器中使用。 http://dev.mysql.com/doc/refman/5.5/en/sql-syntax-prepared-statements.html – Devart

+0

是的,你是对的...想法:我们可以将旧内容和新内容复制到临时表(s)并调用将创建并执行预准备语句的存储过程。但它会非常昂贵。 –