Perhaps something like:
DELIMITER $$
CREATE TRIGGER `AuditUserTrigger`
BEFORE UPDATE ON `Users`
FOR EACH ROW BEGIN
INSERT INTO `aUsers`
SELECT `Users`.*
FROM `Users`
INNER JOIN `AuditTables`
ON `AuditTables`.`name` = 'Users'
AND `AuditTables`.`enabled` = 1
WHERE `Users`.`id` = OLD.`id`;
END$$
DELIMITER ;
EDIT
By way of an explanation:
I have an Audit table defined as
CREATE TABLE IF NOT EXISTS `AuditTables` (
`id` int(12) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(64) NOT NULL,
`enabled` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `auditTable` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1
;
which contains an entry for every core table in the database, together with the active flag that can be set to true or false (1 or 0) depending on whether I want that table to be audited or not.
For my Users
table (as shown in the original example) I have a corresponding audit table (aUsers
) with an identical structure, but without unique keys, that can hold all the "historic" records from the Users
table. The ON UPDATE trigger on Users
will save the OLD Users
table record to aUsers
if auditing is enabled for the Users
table before executing the actual UPDATE against the user record.
All records in all tables also have the following columns:
`archived` tinyint(1) NOT NULL DEFAULT '0',
`createdAt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`createdBy` int(12) unsigned NOT NULL DEFAULT 0,
`updatedAt` datetime ON UPDATE CURRENT_TIMESTAMP,
`updatedBy` int(12) unsigned DEFAULT NULL,
giving me details of who an when updates were done, while the archived
flag is set as a "soft delete"
createdBy
and updatedBy
are managed by my code, with an element in my model layer that automatically injects the session user ID into that property.
updatedAt datetime ON UPDATE CURRENT_TIMESTAMP,
requires MySQL 5.6