MySQL for 触发器中的循环
MySQL for loop in trigger
我有 2 个 table:
- employees 包括列 id、name、job_title
- 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;
我有 2 个 table:
- employees 包括列 id、name、job_title
- 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;