【发布时间】:2019-11-26 16:11:55
【问题描述】:
当日志记录打开时,我正在尝试使用 MySQL 中的触发器来更新带有表更改的日志表。
UPDATE 触发器需要遍历表的所有字段,比较数据变化(OLD.fieldname NEW.fieldname),然后将字段名称和数据写入日志表。
我编写的代码必须明确命名每个字段。有些表有很多字段,我不想手动输入所有字段名称。
有没有办法以编程方式遍历表的字段,以便我可以创建一个存储过程来调用?
我的代码:
CREATE DEFINER=`root`@`localhost` TRIGGER `trgUserUpd` AFTER UPDATE ON `user`
FOR EACH ROW BEGIN
DECLARE rChanges TEXT DEFAULT '';
IF BINARY(OLD.userName) <> BINARY(NEW.userName) THEN
SET rChanges := CONCAT('userName: ', OLD.userName, ' => ', NEW.userName);
END IF;
IF BINARY(OLD.fullName) <> BINARY(NEW.fullName) THEN
IF rChanges <> '' THEN
SET rChanges := CONCAT(rChanges, '
');
END IF;
SET rChanges := CONCAT(rChanges, 'fullName: ', OLD.fullName, ' => ', NEW.fullName);
END IF;
IF BINARY(OLD.initials) <> BINARY(NEW.initials) THEN
IF rChanges <> '' THEN
SET rChanges := CONCAT(rChanges, '
');
END IF;
SET rChanges := CONCAT(rChanges, 'initials: ', OLD.initials, ' => ', NEW.initials);
END IF;
IF BINARY(OLD.password) <> BINARY(NEW.password) THEN
IF rChanges <> '' THEN
SET rChanges := CONCAT(rChanges, '
');
END IF;
SET rChanges := CONCAT(rChanges, 'password changed');
END IF;
IF BINARY(OLD.salt) <> BINARY(NEW.salt) THEN
IF rChanges <> '' THEN
SET rChanges := CONCAT(rChanges, '
');
END IF;
SET rChanges := CONCAT(rChanges, 'salt: ', OLD.salt, ' => ', NEW.salt);
END IF;
IF BINARY(OLD.administrator) <> BINARY(NEW.administrator) THEN
IF rChanges <> '' THEN
SET rChanges := CONCAT(rChanges, '
');
END IF;
SET rChanges := CONCAT(rChanges, 'administrator: ', OLD.administrator, ' => ', NEW.administrator);
END IF;
IF BINARY(OLD.active) <> BINARY(NEW.active) THEN
IF rChanges <> '' THEN
SET rChanges := CONCAT(rChanges, '
');
END IF;
SET rChanges := CONCAT(rChanges, 'active: ', OLD.active, ' => ', NEW.active);
END IF;
CALL ChangeNotify('user', OLD.id, rChanges, 'update');
END;
似乎准备好的语句也不起作用。我刚试过:
BEGIN
DECLARE rChanges TEXT DEFAULT '';
DECLARE eof INT DEFAULT FALSE;
DECLARE field CHAR(50) DEFAULT '';
DECLARE query, stmt CHAR(200) DEFAULT '';
DECLARE oldValue, newValue TEXT DEFAULT '';
DECLARE fields CURSOR FOR
SELECT column_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'user'
ORDER BY ordinal_position;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET eof = TRUE;
OPEN fields;
REPEAT
FETCH fields INTO field;
IF NOT eof THEN
SET query = CONCAT('SELECT OLD.', field, ', NEW.', field, ' INTO oldValue, newValue');
PREPARE stmt FROM query;
EXECUTE stmt;
IF BINARY(oldValue) <> BINARY(newValue) THEN
IF rChanges <> '' THEN
SET rChanges := CONCAT(rChanges, '
');
END IF;
SET rChanges := CONCAT(rChanges, field, ': ', oldValue, ' => ', newValue);
END IF;
END IF;
UNTIL eof = TRUE;
END REPEAT;
CLOSE fields;
CALL ChangeNotify('user', OLD.id, rChanges, 'update');
END
这甚至不会保存(除非我有什么问题)。
【问题讨论】:
标签: mysql stored-procedures triggers