当我更新另一个字段时,意外触发了字段上的触发器

时间:2011-07-26 02:38:28

标签: mysql triggers

这是我的表:

Id    Password       Status
1     a6cc890..       1

我在密码上有一个触发器,用于加密字段。

触发器如下:

-- Trigger DDL Statements
DELIMITER $$

USE `ediftpdb`$$

CREATE
DEFINER=`edidbo`@`%`
TRIGGER `ediftpdb`.`trigger_format_passwd`
BEFORE INSERT ON `ediftpdb`.`users`
FOR EACH ROW
SET NEW.passwd=md5(NEW.passwd)$$

CREATE
DEFINER=`edidbo`@`%`
TRIGGER `ediftpdb`.`trigger_format_passwd_update`
BEFORE UPDATE ON `ediftpdb`.`users`
FOR EACH ROW
SET NEW.passwd=md5(NEW.passwd)$$

令我惊讶的是,当我更新状态时会触发触发器,并且密码再次加密!

我该怎么做才能解决这个问题?

2 个答案:

答案 0 :(得分:1)

如果更新Status,则表示您正在进行更新,并且所有UPDATE触发器都将触发。您需要做的就是比较passwd的新旧值,只有在它们不同时才应用您的MD5。幸运的是,MySQL提供OLD and NEW row aliases

  

您可以使用别名OLDNEW来引用主题表(与触发器关联的表)中的列。 OLD.col_name在更新或删除之前引用现有行的列。 NEW.col_name指的是要插入的新行的列或更新后的现有行。尝试使用IF

BEFORE UPDATE ON `ediftpdb`.`users`
FOR EACH ROW
SET NEW.passwd = IF(NEW.passwd = OLD.passwd, NEW.passwd, md5(NEW.passwd))

除非NEW.passwd(新密码)和NEW.passwd(数据库中已有的哈希密码)不同,否则不应更改OLD.passwd。当然,如果有人设法输入旧密码的MD5作为新密码,这可能会失败,但这种情况不太可能。

答案 1 :(得分:0)

当您“更新Status”时,您实际上是在整个表格上执行UPDATE。你只修改一个字段的值的事实不会进入它!

您可以使用the NEW and OLD identifiers手动检查passwd的值是否已更改。