2016-06-30 45 views
0

在這裏我有一個工作的MySQL觸發器:Mysql觸發器優化。多個表列的IF(OLD.data <> NEW.data)

DROP TRIGGER IF EXISTS trg_after_update_tbl1; 
DELIMITER // 
CREATE TRIGGER trg_after_update_tbl1 
    AFTER UPDATE ON db1.tbl1 FOR EACH ROW 
    BEGIN 
    DECLARE strOld VARCHAR(255); 
    DECLARE strNew VARCHAR(255); 
    SET strOld = ''; 
    SET strNew = ''; 

    IF (NEW.colA <> OLD.colA) THEN 
     SET strOld = CONCAT(strOld, 'colA: ',OLD.colA,'; '); 
     SET strNew = CONCAT(strNew, 'colA: ',NEW.colA,'; '); 
    END IF; 
    IF (NEW.colB <> OLD.colB) THEN 
     SET strOld = CONCAT(strOld, 'colB: ',OLD.colB,'; '); 
     SET strNew = CONCAT(strNew, 'colB: ',NEW.colB,'; '); 
    END IF; 
    IF (NEW.colC <> OLD.colC) THEN 
     SET strOld = CONCAT(strOld, 'colC: ',OLD.colC,'; '); 
     SET strNew = CONCAT(strNew, 'colC: ',NEW.colC,'; '); 
    END IF; 
    -- AND SO MANY COLUMN CLAUSES ON.... 

    INSERT INTO db1.changes (user, tableName, oldData, newData, date) 
    VALUES (
      user(), 
      'tableA', 
      strOld, 
      strNew, 
      now() 
     ); 
    END// 
DELIMITER ; 

是否有可能表的列名分配給一個變量(可以說X)從列表,數組或類似的東西,遍歷它並使用一個IF子句?像這樣(僞):

BEGIN LOOP 
     IF (NEW.X <> OLD.X) THEN 
      SET strOld = CONCAT(strOld, X, ': ',OLD.X,'; '); 
      SET strNew = CONCAT(strNew, X, ': ',NEW.X,'; '); 
     END IF; 
END LOOP 
+0

「這麼多專欄......」 - 255會夠嗎? –

+0

是的,它實際上:D –

回答

1

無論DBMS的使用,你的建議通常被稱爲動態SQL,這意味着你正在執行的語句將第一個需要加以編譯,然後執行。

儘管您可能會減少代碼行數量,但也會影響(消極)性能。

正如我常說的,你寫的代碼一次,但你讀了很多次,並運行它,甚至更多次。道德:在需要時,花費一些額外的努力使代碼易讀和高效。

在任何情況下,MySQL都提供Prepared Statements這是它的Dynamic SQL版本。

有一個例外,我上面寫了:當你的兩個表包含知道列數,所有相同的類型。在這種情況下,您可以將兩條記錄的內容選擇爲兩個數組,然後遍歷數組(然而這只是最後一刻的想法)。