Suppose we have 50 tables
in a database and we want to capture all the changes (Previous value and new value of columns) across the columns of each table. An au
This is a little bit improved version of Vlad answer. Audit table has column for 'diff' of changes.
Auditing rules:
INSERT
and DELETE
- complete record with all fields is stored to audit tableUPDATE
- only changes on fields is storedAudit table structure. diff
is column where changes are stored.
NB: privileges
is JSON column on table we are auditing in this case.
CREATE TABLE roles_audit_log (
roles_id INT UNSIGNED NOT NULL,
diff JSON,
dml_type ENUM('INSERT', 'UPDATE', 'DELETE') NOT NULL,
dml_timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
dml_created_by VARCHAR(255) NOT NULL default 'system',
PRIMARY KEY (roles_id, dml_type, dml_timestamp)
);
Trigger for UPDATE
statement. Will fill diff
column with fields that were changed.
DELIMITER $$
CREATE TRIGGER roles_audit_au AFTER UPDATE ON `roles` FOR EACH ROW
BEGIN
DECLARE m_change text;
SET m_change = JSON_OBJECT();
IF coalesce(NEW.role, '') != coalesce(OLD.role, '') THEN
SET m_change = JSON_SET(m_change, '$.role', NEW.role);
END IF;
IF coalesce(NEW.created_at, '') != coalesce(OLD.created_at, '') THEN
SET m_change = JSON_SET(m_change, '$.created_at', NEW.created_at);
END IF;
IF coalesce(NEW.updated_at, '') != coalesce(OLD.updated_at, '') THEN
SET m_change = JSON_SET(m_change, '$.updated_at', NEW.updated_at);
END IF;
IF coalesce(NEW.privileges, '') != coalesce(OLD.privileges, '') THEN
SET m_change = JSON_SET(m_change, '$.privileges', NEW.privileges);
END IF;
INSERT INTO `roles_audit_log` (
roles_id,
diff,
dml_type,
dml_created_by
) VALUES(
NEW.id,
m_change,
'UPDATE',
coalesce(@logged_user, 'system')
);
END;$$
DELIMITER ;
Trigger for DELETE
statement. Will fill diff
with complete row that was deleted.
DELIMITER $$
CREATE TRIGGER roles_audit_ad AFTER DELETE ON `roles` FOR EACH ROW
BEGIN
INSERT INTO `roles_audit_log` (
roles_id,
diff,
dml_type,
dml_created_by
) VALUES(
OLD.id,
JSON_OBJECT(
'id', OLD.id,
'role', OLD.role,
'privileges', OLD.privileges,
'created_at', OLD.created_at,
'updated_at', OLD.updated_at
),
'DELETE',
coalesce(@logged_user, 'system')
);
END;$$
DELIMITER ;
Trigger for INSERT
statement. Will fill diff
with complete row that was deleted.
DELIMITER $$
CREATE TRIGGER roles_audit_ai AFTER INSERT ON `roles` FOR EACH ROW
BEGIN
INSERT INTO `roles_audit_log` (
roles_id,
diff,
dml_type,
dml_created_by
) VALUES(
NEW.id,
JSON_OBJECT(
'id', NEW.id,
'role', NEW.role,
'privileges', NEW.privileges,
'created_at', NEW.created_at,
'updated_at', NEW.updated_at
),
'INSERT',
coalesce(@logged_user, 'system')
);
END;$$
DELIMITER ;