2017-03-21 24 views
1

我有用于存储用户评级的名为pledgeRating的表。在每次插入我运行下面的触发器在pledgeTemplate表更新ratingsCountrating列:检测更新查询是否来自触发器

CREATE DEFINER=`trigger`@`%` TRIGGER `project87`.`pledgeRating_AFTER_INSERT` AFTER INSERT ON `pledgeRating` FOR EACH ROW 
BEGIN 
    UPDATE `pledgeTemplate` 
     SET `rating` = ((`rating` * `ratingsCount`) + NEW.rating)/(`ratingsCount` + 1), 
      `ratingsCount` = `ratingsCount` + 1 
     WHERE `id` = NEW.pledgeTemplateID; 
END 

为了完整起见,我想阻止所有的MySQL用户从pledgeTemplate表中直接更新ratingsCountrating列。我希望这两列只能从触发器更新。

为了实现这个目标我已经在pledgeTemplate表中创建一个新的触发器来验证用户身份运行更新查询,但如果更新是从触发与否我不能找到一种方法来检测:

CREATE DEFINER=`trigger`@`%` TRIGGER `project87`.`pledgeTemplate_BEFORE_UPDATE` BEFORE UPDATE ON `pledgeTemplate` FOR EACH ROW 
BEGIN 
    IF (OLD.ratingsCount != NEW.ratingsCount OR OLD.rating != NEW.rating) AND {{Update query is not from the trigger}} THEN 
     SIGNAL sqlstate '45000' SET message_text = 'Error: Only trigger can modify ratingsCount or rating columns'; 
    END IF; 
END 

是否有可能从第一个触发器传递一个标志,以便我可以在第二个触发器中检测到查询是否来自触发器?我查看了CURRENT_USER对象和USER()函数,因为我认为这些可能有帮助。然而,CURRENT_USER总是设置为DEFINERUSER()始终返回运行初始查询的用户。

那么,有什么办法来检测pledgeTemplate表上的更新查询是否从触发器或“直接”更新运行?

+1

我不认为这是可能的,但你可以删除你的用户在各自表上的更新权限 – Mihai

+0

事情是,我仍然需要我的用户更新'pledgeTemplate'表。如果我删除UPDATE权限,那么我将停止所有更新。我只是想保护这两列不被触发器更新。 – Guferos

回答

0

Hello_

首先我开始解释评论我的想法,但似乎它变得过长,格式不正确。因此,这只是一个想法,我不知道,如果你是与它的罚款,但我会分享:

  1. ALTER TABLE pledgeTemplate ADD COLUMN isTriggerUpdate BIT NULL DEFAULT 0; - 所以我们在表中添加一列,我们可以为标志来确定是否使用更新从触发器或用户

2.

CREATE DEFINER=`trigger`@`%` TRIGGER `project87`.`pledgeRating_AFTER_INSERT` 
AFTER INSERT ON `pledgeRating` FOR EACH ROW 
BEGIN 
    UPDATE `pledgeTemplate` 
     SET `rating` = ((`rating` * `ratingsCount`) + NEW.rating)/(`ratingsCount` + 1), 
      `ratingsCount` = `ratingsCount` + 1, 
      `isTriggerUpdate ` = 1 
     WHERE `id` = NEW.pledgeTemplateID; 
END 

更改您的触发pledgeRating_AFTER_INSERT的代码来设置标志列真

到来

3.

CREATE DEFINER=`trigger`@`%` TRIGGER `project87`.`pledgeTemplate_BEFORE_UPDATE` 
BEFORE UPDATE ON `pledgeTemplate` FOR EACH ROW 
BEGIN 
    IF (OLD.ratingsCount != NEW.ratingsCount OR OLD.rating != NEW.rating) 
     AND NEW.isTriggerUpdate != 1 THEN 
     SIGNAL sqlstate '45000' SET message_text = 'Error: Only trigger can modify ratingsCount or rating columns'; 
    END IF; 
END 

现在你可以有缺失的条件pledgeTemplate_BEFORE_UPDATE这样。

我认为这将作为逻辑工作,但问题是,这是实现这一点最有效的逻辑。在这个逻辑中,您不必在任何情况下向前端公开isTriggerUpdate列,因为只需将其设置为true即可绕过此逻辑...

祝您好运!

相关问题