MySQL存储过程循环增量值,仅获取最终值

时间:2017-11-20 09:30:08

标签: mysql procedure

我正在编写一个非常简单的程序来更新“todo”中的位置INT列。现有行的表。目标是为每个用户逐步设置位置值,从0开始。运行代码时,它似乎只捕获每个用户循环的最终值。有什么我对MySQL的变量有误解吗?或许我弄乱了循环..

这是一个深夜>。<

BEGIN
    DECLARE loop_done INT DEFAULT 0;
    DECLARE current_user_id INT;
    DECLARE current_todo_id INT;
    DECLARE todo_position INT DEFAULT 0;
    DECLARE cur_users CURSOR FOR 
        SELECT id FROM users;
    DECLARE cur_todos CURSOR FOR 
        SELECT id FROM todo WHERE user_id = @uid;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET loop_done = 1;

    OPEN cur_users;
    loop_users: LOOP 

        FETCH cur_users INTO current_user_id;

        IF loop_done = 1 THEN
            SET loop_done = 0;
            LEAVE loop_users;
        END IF;

        SET @uid = current_user_id;
        SET todo_position = 0;

        OPEN cur_todos;

        loop_todos: LOOP 
            FETCH cur_todos INTO current_todo_id;
            IF loop_done = 1 THEN
                SET loop_done = 0;
                SET todo_position = 0; 
                LEAVE loop_todos;
            END IF;

            UPDATE todo SET position = todo_position WHERE user_id = @uid;
            SET todo_position = todo_position + 1;

        END LOOP loop_todos;

        CLOSE cur_todos;

    END LOOP loop_users;
END$$

以下是实际结果:

+----------+
| position |
+----------+
|        3 |
|        3 |
|        3 |
|        3 |
|        4 |
|        4 |
|        4 |
|        4 |
|        4 |
+----------+

这些是预期结果:

+----------+
| position |
+----------+
|        0 |
|        1 |
|        2 |
|        3 |
|        0 |
|        1 |
|        2 |
|        3 |
|        4 |
+----------+

1 个答案:

答案 0 :(得分:1)

我认为你根本不需要游标

drop table if exists todo;

create table todo (id int, user_id int, position int);

truncate table todo;
insert into todo values (1,1,null),(2,1,null),(2,2,null);


update todo t join  (
            select id,user_id, 
            if(user_id <> @p,@rn:=0,@rn:=@rn+1) rn ,
            @p:=user_id p
            from todo, (select @rn:=0,@p:=0) r
            order by user_id,id
            ) s on s.id = t.id and s.user_id = t.user_id
    set position = s.rn

    where 1  = 1;

使用变量模拟其他dbs中的行号函数并返回

select * from todo;

+------+---------+----------+
| id   | user_id | position |
+------+---------+----------+
|    1 |       1 |        0 |
|    2 |       1 |        1 |
|    2 |       2 |        0 |
+------+---------+----------+
3 rows in set (0.02 sec)