【MySQL】定时任务

365 阅读2分钟

主要用于数据统计

使用 Navicat for MySQL 工具

1.配置

开启事件调度器
SET GLOBAL event_scheduler = 1;

2.创建事件

新建一个事件,定义事件内容:调用一个定义好的函数

设置任务计划为每 n 年/月/日/时/分/秒 执行,并于某一时间点开始,如下图,设置为自2020年3月17日起每天执行

3.创建函数

不用传参和获取返回值,这里选择创建‘过程’,定义如下
BEGIN
	DECLARE _user_id INT DEFAULT 0;   # 用户编号
	DECLARE _type INT DEFAULT 0;      # 工单类型
	DECLARE _num INT DEFAULT 0;       # 工单数量
	DECLARE _resource INT DEFAULT 0;  # 上传资源数量
	DECLARE _date INT DEFAULT 0;      # 执行时间 - 时间戳
	DECLARE _year INT DEFAULT 0;      # 年
	DECLARE _month INT DEFAULT 0;     # 月
	DECLARE _day INT DEFAULT 0;       # 日
	DECLARE _flag INT DEFAULT 0;      # 游标循环条件
	DECLARE _cursor_res CURSOR FOR SELECT id FROM sys_rbac_user WHERE is_user = 1; # 获取所有可登录系统的用户
	DECLARE CONTINUE HANDLER FOR NOT FOUND SET _flag = 1;
	# 设置日期
	SET _date = UNIX_TIMESTAMP(NOW());
	SET _year = date_format(now(),'%Y');
	SET _month = date_format(now(),'%m');
	SET _day = date_format(now(),'%d');
	# 循环获取人员列表
	OPEN _cursor_res;
		WHILE _flag = 0 DO
			FETCH _cursor_res INTO _user_id;
			IF _flag = 0 THEN
				# 各类型工单总量
				BEGIN
					DECLARE _flag_num INT DEFAULT 0; # 游标循环条件
					DECLARE _cursor_type_num CURSOR FOR 
						SELECT type,count(*) AS num 
						FROM t_project_event
						WHERE create_time > UNIX_TIMESTAMP(NOW()) - 24*60*60 # 工单上传时间-按天统计
						AND uid = _user_id # 当前用用户发起的;
						AND state = 2 # 审核通过
						GROUP BY type;
					DECLARE CONTINUE HANDLER FOR NOT FOUND SET _flag_num = 1;
					OPEN _cursor_type_num;
						WHILE _flag_num = 0 DO
							FETCH _cursor_type_num INTO _type,_num;
							IF _flag_num = 0 THEN
									INSERT INTO aibs_report_daily_user_create
										(user_id,type,num,resource,date,`year`,`month`,`day`) 
									VALUES 
										(_user_id,_type,_num,0,_date,_year,_month,_day);
							END IF;
						END WHILE;
					CLOSE _cursor_type_num;
				END;
				# 各类型工单资源上传总量
				BEGIN
					DECLARE _is_exists INT DEFAULT 0; # 工单是否存在标志位
					DECLARE _flag_resource INT DEFAULT 0; # 游标循环条件
					DECLARE _cursor_type_resource CURSOR FOR 
						SELECT type,count(*) as resource
						FROM t_project_event AS e
						RIGHT JOIN t_project_event_res AS r 
						ON r.event_id = e.id
						WHERE e.type = r.res_type # 资源类型与工单类型一致
						AND r.create_time > UNIX_TIMESTAMP(NOW()) - 24*60*60 # 资源上传时间-按天统计
						AND e.uid = _user_id # 当前用用户发起的工单
						AND r.user_id = _user_id #当前用户上传的资源
						AND e.state = 2 # 审核通过
						GROUP BY e.type
						ORDER BY e.id ASC;
					DECLARE CONTINUE HANDLER FOR NOT FOUND SET _flag_resource = 1;
					OPEN _cursor_type_resource;
						WHILE _flag_resource = 0 DO
							FETCH _cursor_type_resource INTO _type,_resource;
							IF _flag_resource = 0 THEN
								# 查询当前工单类型记录是否存在 (特别需要注意,例如:本日没有设计工单,但本日在以前的设计工单中上传了设计图的情况)
								SELECT count(*) as is_exists into _is_exists FROM aibs_report_daily_user_create WHERE type = _type AND user_id = _user_id;
								# 有责改之,无则新增
								IF _is_exists = 0 THEN
										INSERT INTO aibs_report_daily_user_create
										(user_id,type,num,resource,date,`year`,`month`,`day`) 
									VALUES 
										(_user_id,_type,0,_resource,_date,_year,_month,_day);
								ELSE
										UPDATE aibs_report_daily_user_create SET
											resource = _resource
										WHERE
											user_id = _user_id AND type = _type;
								END IF;
							END IF;
						END WHILE;
					CLOSE _cursor_type_resource;
				END;
			END IF;
		END WHILE;
	CLOSE _cursor_res;
END

使用发现,事件定义中只能调用一个过程,如果需要执行多个任务,可以在事件中调用一个任务列表过程,如图,在事件列表中调用daily_count,再由daily_count过程依次调用其他多个过程