以前一直没写过存储过程,今天接到学校那边一个需求,要求给数据库去重,正好用存储过程试了一下

需求:现有一批打卡记录,每人(学号标识)每天(打卡日期)可能有多条记录,要求只留下最新的那条记录

下面是代码:

CREATE DEFINER=`liu`@`%` PROCEDURE `we_mrdk`()
BEGIN
    -- 删除we_mrdk表的重复数据
    -- 每人仅保留每天最后一条打卡数据
    
    -- 设置学号遍历结束标志变量默认值0【0-未遍历完 1-已遍历完】
    DECLARE loop_flag INT(1) DEFAULT 0;
    -- 用于遍历的每个学生学号
    DECLARE student_id VARCHAR(20) DEFAULT '0';
    -- 用于遍历的每天的日期
    DECLARE date_item VARCHAR(20) DEFAULT '';
    -- 需要删除的记录的id
    DECLARE log_id VARCHAR(20) DEFAULT '0';

    
    -- 查询所有学号并赋值到studentIdList
    DECLARE student_id_list CURSOR FOR SELECT DISTINCT we_mrdk.xh FROM we_mrdk ORDER BY we_mrdk.xh DESC;
    -- 查询所有日期并赋值到dateList
    DECLARE date_list CURSOR FOR SELECT DATE_FORMAT(we_mrdk.created_at,'%Y-%m-%d') AS date FROM we_mrdk GROUP BY date;
    
    -- 指定游标遍历结束时设置loop_flag为1
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET loop_flag=1;
    
    OPEN date_list;
        -- 开始遍历日期列表
        date:LOOP
            -- 取一条日期
            FETCH date_list INTO date_item;
            
            -- 判断循环标志位,是否遍历完
            IF loop_flag<>0 THEN
                LEAVE date;
            END IF;
            
            -- 开始遍历学号列表
            OPEN student_id_list;        
                student:LOOP
                    -- 取一个学号
                    FETCH student_id_list INTO student_id;
                    
                    -- 判断循环标志位,是否遍历完
                    IF loop_flag=1 THEN
                        LEAVE student;
                    END IF;        

                    -- 遍历一个学生一天的打卡记录
                    student_date:LOOP
                        -- 查询指定学号,指定日期是否有多余1条的记录
                        SELECT
                            we_mrdk.log_id INTO log_id
                        FROM
                            we_mrdk 
                        WHERE
                            we_mrdk.xh = student_id 
                            AND we_mrdk.created_at >= date_item 
                            AND we_mrdk.created_at <= DATE_ADD( STR_TO_DATE( date_item, '%Y-%m-%d' ), INTERVAL 1 DAY ) 
                        ORDER BY we_mrdk.created_at DESC
                        LIMIT 1,1;

                        -- 判断是否有大于1条记录
                        IF log_id=0 THEN
                            -- 只有一条记录
                            -- 恢复循环标志位
                            SET loop_flag=0;
                            -- 恢复打卡记录id标志位
                            SET log_id='0';
                            -- 退出循环
                            LEAVE student_date;
                        ELSE
                            -- 进行删除操作
                            DELETE FROM we_mrdk WHERE we_mrdk.log_id=log_id;
                            -- 恢复打卡记录id标志位
                            SET log_id='0';
                        END IF;
                    END LOOP student_date;
                END LOOP student;
            -- 关闭游标
            CLOSE student_id_list;
            -- 恢复循环标志位
            SET loop_flag=0;
        END LOOP date;
    CLOSE date_list;
END
总结:存储过程写起来太恶心了,没有代码提示,看起来结构也混乱,可维护性也差,实在不如用代码操作来得舒服
Last modification:February 4th, 2020 at 01:46 pm