MySQL for 触发器中的循环

MySQL for loop in trigger

我有 2 个 table:

  1. employees 包括列 id、name、job_title
  2. employees_audit 包括列 id、employees_id、名称、job_title、updated_date、操作

我有一个现在可以正常工作的触发器...:

CREATE TRIGGER after_update_employees

AFTER UPDATE ON employees FOR EACH ROW

BEGIN

    IF OLD.name <> new.name THEN
        INSERT INTO employees_audit(employee_id, name,change_date,action)
        VALUES(OLD.id, concat('Old:', OLD.first_name, 'New:', new.first_name,'"'),NOW(),"update");
    END IF;

    IF OLD.job_title <> new.job_title THEN
        INSERT INTO employees_audit(employee_id, job_title, change_date,action)
        VALUES(OLD.id, concat('Old:', OLD.job_title, 'New:', new.job_title,'"'),NOW(),"update");
    END IF;

END$$

.. 但是,如果我为员工 table 中的相同 ID 更新 2 个条件,我的触发器会创建 2 个单独的行(每个条件一个),但我宁愿让我的触发器只说明所有更新同一行上的相同 id。

例如:

UPDATE employees
SET job_title = "programmer", first_name = "Vic"
WHERE employee_number =1;

触发器的结果 1

是否可以通过某种方式将我的触发器重写为循环?

考虑使用 case 表达式:

IF OLD.name <> NEW.name OR OLD.job_title <> NEW.job_title THEN
    INSERT INTO employees_audit (employee_id, name, job_title, change_date,action)
    VALUES(
        OLD.id, 
        CASE WHEN OLD.name <> NEW.name THEN 
            CONCAT('Old:', OLD.name, 'New:', NEW.name, '''')
        END,
        CASE WHEN OLD.job_title <> new.job_title THEN 
            CONCAT('Old:', OLD.job_title, 'New:', NEW.job_title, '''')
        END,
        NOW(), 
        'update'
END IF;

请注意,我修改了值插入 name 的列(您正在检查 name 但插入 fist_name,这没有多大意义)。另外,我用单引号替换了双引号(对字符串使用双引号不是一个好习惯,尽管 MySQL 支持它,因为它偏离了 SQL 标准)。

如果列可以为空,则需要额外的逻辑:

IF NOT OLD.name <=> NEW.name OR NOT OLD.job_title <=> NEW.job_title THEN
    INSERT INTO employees_audit (employee_id, name, job_title, change_date,action)
    VALUES(
        OLD.id, 
        CASE WHEN OLD.name <> NEW.name THEN 
            CONCAT('Old:', COALESCE(OLD.name, ''), 'New:', COALESCE(NEW.name, ''), '''')
        END,
        CASE WHEN OLD.job_title <> new.job_title THEN 
            CONCAT('Old:', COALESCE(OLD.job_title, ''), 'New:', COALESCE(NEW.job_title, ''), '''')
        END,
        NOW(), 
        'update'
END IF;