在工作中遇到要程序根据时间自动增加工龄的需求。
php没办法自己发起请求,又不想在服务器上写计划任务crontab,通过用户请求来更改又不能保证用户会去操作。
用数据库的存储过程和事件来完成。
数据库里有创建时间字段(created)和工龄(working_years)字段。
存储过程:
DROP PROCEDURE if EXISTS auto_working_years;CREATE PROCEDURE auto_working_years()BEGIN DECLARE ns INT DEFAULT 1; DECLARE myuid INT DEFAULT 0; DECLARE cur1 CURSOR FOR SELECT uid FROM `user` WHERE (role='ganger' OR role='worker') AND (DATEDIFF(CURRENT_DATE(),created)>365); DECLARE EXIT HANDLER FOR NOT FOUND SET ns = 0; OPEN cur1; WHILE ns <> 0 DO FETCH cur1 into myuid; UPDATE `user` SET working_years = working_years+1 , created = DATE_ADD(created,INTERVAL 365 DAY) WHERE uid = myuid; END WHILE; CLOSE cur1;END;call auto_working_years();
首先定义游标,查询语句筛选出user表里角色是工人和工长的创建时间大于365天的记录。
开启游标
更新这些记录的表字段工龄+1,同时修改创建时间加一年,这里可以另创建一个字段用于对已经增加了工龄的记录做标记。把创建时间这一列复制过去。用新的字段来做判断就不会影响到创建时间。
这里用了两个mysql的系统时间函数 分别是DATEDIFF和DATE_ADD,一个获取时间差,一个增加时间间隔,间隔时间可以自己定义单位。
参数ns用于做是否执行循环的判断。
关闭游标
call用于调用存储过程。
还有个问题是存储过程执行过后记录已经更改但是显示的受影响行数是0
存储过程写完了接下来就是定时器了。我定义这个存储过程每周执行一次。
drop event if exists workingyearsEvent;create event workingyearsEventon schedule every 7 day starts '2019-1-16 0:0:0'on completion PRESERVE do call auto_working_years();
剩下的就是需要打开mysql里面的一些设置
检查事件任务是否开启 SHOW VARIABLES LIKE 'event_scheduler';
set GLOBAL event_scheduler = 1;
ALTER EVENT workingyearsEvent ENABLE;
保证定时任务能正常执行了。