2011-08-03 59 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)並調用將創建並執行預準備語句的存儲過程。但它會非常昂貴。 –