MySQL触发器以更新具有多对多关系的所有条目

时间:2014-08-01 14:59:00

标签: mysql triggers

我正在尝试创建一个MySQL触发器,如果​​更新了级别奖励,它将更新我的所有用户分数。我已经解决了旧奖励和新奖励之间的差异,但我仍然坚持如何更新已经完成该等级的每个用户分数。下面是一个简化的表格结构。

Users
+---------+-------+
| user_id | score |
+---------+-------+

Users_levels
+---------+----------+
| user_id | level_id |
+---------+----------+

Levels
+----------+---------+
| level_id | tier_id |
+----------+---------+

Tier_reward
+---------+----------+
| tier_id | reward   |
+---------+----------+   

到目前为止我已经走了多远:

CREATE TRIGGER update_level_reward AFTER UPDATE ON tier_reward FOR EACH ROW
    BEGIN
        DECLARE REWARD INT;
        SET REWARD = OLD.reward - NEW.reward;

        -- UPDATE users SET score = score - REWARD WHERE user_id = ;
    END$$

我尝试了以下方面的内容:

UPDATE users
INNER JOIN users_levels
ON users.user_id = users_levels.user_id
INNER JOIN levels
ON users_levels.level_id = levels.level_id
SET score = score - REWARD
WHERE levels.tier = OLD.tier;

然而,即使用户已完成该级别的多个级别,这也只会降低一次得分。

示例

Users
+---------+-------+
| user_id | score |
+---------+-------+
| 1       | 400   |
| 2       | 700   |
+---------+-------+

Users_levels
+---------+----------+
| user_id | level_id |
+---------+----------+
| 1       | 1        |
| 1       | 2        |
| 2       | 1        |
| 2       | 3        |
+---------+----------+

Levels
+----------+---------+
| level_id | tier_id |
+----------+---------+
| 1        | 1       |
| 2        | 1       |
| 3        | 2       |
+----------+---------+

Tier_reward
+---------+----------+
| tier_id | reward   |
+---------+----------+
| 1       | 200      |
| 2       | 500      |
+---------+----------+ 

现在,如果tier_id 1的奖励减少到100.用户1现在应该得分为200,因为他们已完成该等级的两个级别。用户2应该只丢失100分,因为他们只完成了该级别的一个级别。

Users
+---------+-------+
| user_id | score |
+---------+-------+
| 1       | 200   |
| 2       | 600   |
+---------+-------+

Tier_reward
+---------+----------+
| tier_id | reward   |
+---------+----------+
| 1       | 100      |
| 2       | 500      |
+---------+----------+ 

1 个答案:

答案 0 :(得分:1)

抱歉延迟!!

您可以执行以下操作,首先需要获得每个用户的每个层数。然后使用cursor设置这些值,最后更新users表。

delimiter //
create trigger update_level_reward after update on tier_reward
for each row 
begin
  DECLARE done INT DEFAULT FALSE;
  DECLARE tier_count int;
  DECLARE user_id_fetch int;
  DECLARE reward INT;
  DECLARE reward_recal int ;
  DECLARE cur CURSOR FOR 
  select 
  ul.user_id, count(*) as total
  from users_levels ul
  join levels l on l.level_id = ul.level_id 
  where l.tier_id = new.tier_id
  group by ul.user_id;

  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
  SET reward = OLD.reward - NEW.reward;
  OPEN cur;
        update_loop: LOOP
            FETCH cur INTO user_id_fetch,tier_count;
            IF done THEN
                LEAVE update_loop;
            END IF;
        set reward_recal = tier_count*reward ;
            update users 
        SET score = score - reward_recal
        where user_id = user_id_fetch ; 
        END LOOP;
    CLOSE cur;
end ; //
delimiter ;

这是我在mysql中所做的事情

create table users (user_id int,score int);
insert into users values (1,400),(2,700);

create table users_levels(user_id int,level_id int);
insert into users_levels values
(1,1),(1,2),(2,1),(2,3);

create table levels (level_id int,tier_id int);
insert into levels values 
(1,1),(2,1),(3,2);

create table tier_reward(tier_id int,reward int);
insert into tier_reward values
(1,200),(2,500);

mysql> update tier_reward set reward = 100 where tier_id = 1 ;
Query OK, 1 row affected (0.15 sec)

mysql> select * from users ;
+---------+-------+
| user_id | score |
+---------+-------+
|       1 |   200 |
|       2 |   600 |
+---------+-------+
2 rows in set (0.00 sec)