Mysql触发器优化。多个表列IF(OLD.data<> NEW.data)

时间:2016-06-30 08:49:39

标签: mysql optimization triggers

这里我有一个有效的MySQL触发器:

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

1 个答案:

答案 0 :(得分:1)

无论使用何种DBMS,您所建议的通常称为动态SQL ,这意味着您正在执行的语句首先需要编译然后执行。

虽然您可以减少代码行数,但也会影响(负面)性能。

正如我经常说的那样,你编写一次代码,但是你多次阅读它并运行它甚至更多次。道德:在需要时,花一些额外的努力来使您的代码可读和高效。

在任何情况下,MySQL都提供Prepared Statements,这是它的动态SQL版本。

我上面写的内容有一个例外:当你的两个表包含已知数量的列时,所有相同的类型。在这种情况下,您可以将两个记录的内容选择为两个数组,然后循环遍历数组(尽管这只是最后一分钟的想法)。