触发器是特殊的数据库对象,当在表上发生INSERT、UPDATE或DELETE事件时,会自动执行特定代码(通常是SQL或过程扩展语言,例如PostgreSQL的PL/pgSQL)。
优点:
缺点:
何时使用:
触发器示例(PostgreSQL):
CREATE TABLE employee_audit ( id SERIAL PRIMARY KEY, employee_id INT, old_salary NUMERIC, new_salary NUMERIC, changed_at TIMESTAMP ); CREATE OR REPLACE FUNCTION audit_salary() RETURNS TRIGGER AS $$ BEGIN IF NEW.salary <> OLD.salary THEN INSERT INTO employee_audit(employee_id, old_salary, new_salary, changed_at) VALUES (OLD.id, OLD.salary, NEW.salary, NOW()); END IF; RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER trg_salary_update AFTER UPDATE ON employees FOR EACH ROW EXECUTE FUNCTION audit_salary();
可以在触发器内更新同一张表吗?会发生什么?
答复:
如果触发器设置为表的UPDATE事件,并且在内部执行该同一表的另一个UPDATE,这将导致无限递归(循环)并导致命令异常结束或触发器深度溢出错误。因此,请始终控制以避免递归,或者使用允许/禁止递归调用的选项。
示例:
-- 这种结构可能会导致触发器循环: CREATE OR REPLACE FUNCTION recursive_update() RETURNS TRIGGER AS $$ BEGIN UPDATE employees SET salary = salary * 1.01 WHERE id = NEW.id; -- 将再次触发 RETURN NEW; END; $$ LANGUAGE plpgsql;
历史
在会计CRM中引入了触发器,以便在更改交易表时自动记录操作。高负载下,服务速度减慢,分析表明:触发器在插入日志中耗费了大量时间且未经过优化(例如,仅记录重要事件)。
历史
在库存管理项目中使用了BEFORE INSERT触发器来计算项目ID。错误的ID逻辑导致数据重复,错误在很长时间内未被发现,因为它在“后台”运行。
历史
在HR平台中,触发器在每次INSERT时会对父表和子表进行批量更新。由于触发器逻辑错误,引发递归,完全阻塞了所有与表的操作。不得不禁用触发器并进行复杂的回滚操作以解锁表。