环境
mysql:5.7.38-0ubuntu0.18.04.1
错误的示范
近期项目需要每天自动生成一个数据表,表名需要带日期,考虑数据写入实时性故以当天生成后一天数据表的方案进行数据表生成。
使用的是mysql的event脚本(若果使用其他脚本估计也不会有这样的经历吧),以下是我的事件脚本:
-- 这是错误的哦
create event createImLogTable on schedule
every '1' DAY
starts '2023-07-02 00:00:00'
on completion preserve
enable
do
BEGIN
SET @sqlStr = CONCAT('create table im_log_', curdate()+1, ' like im_log');
PREPARE stmt1 FROM @sqlStr; EXECUTE stmt1;
END;
-- 我们打印下sqlStr
select CONCAT('create table im_log_', curdate()+1, ' like im_log');
-- 运行结果: create table im_log_20230819 like im_log
看sqlStr结果好像没有什么问题,那么问题出现在什么地方呢?到了月底查看日志发现大量数据写入失败发现20230801的数据表未被创建,出现如下问题:
-- 加减法测试
select curdate()+20, CONCAT('create table im_log_', curdate()+20, ' like im_log');
-- 运行结果: 20230838, create table im_log_20230838 like im_log
select curdate()-20, CONCAT('create table im_log_', curdate()-20, ' like im_log');
-- 运行结果: 20230798, create table im_log_20230798 like im_log
select curdate()+100, CONCAT('create table im_log_', curdate()+100, ' like im_log');
-- 运行结果: 20230918, create table im_log_20230918 like im_log
做加减测试后发现,curdate()函数获取的日期如果直接进行运算会被当成十进制数字进行计算,而不会按照日期进行计算,故curdate()+1,curdate()+N等用法为错误的用法。curdate()也可以进行乘除运算哦,由此我得出结论curdate()直接参与运算会被转换为当天%Y%m%d格式日期的十进制数字进行运算。
-- 乘除运算
select curdate()*2, CONCAT('create table im_log_', curdate()*2, ' like im_log');
-- 运行结果: 40461636, create table im_log_40461636 like im_log
select curdate()/2, CONCAT('create table im_log_', curdate()/2, ' like im_log');
-- 运行结果: 10115409.0000, create table im_log_10115409.0000 like im_log
正确用法
先来看看修改后的脚本:
-- 新的event脚本
create event createImLogTable on schedule
every '1' DAY
starts '2023-08-02 00:00:00'
on completion preserve
enable
do
BEGIN
SET @sqlStr = CONCAT('create table im_log_', DATE_FORMAT(date_add(curdate(),interval 1 day), '%Y%m%d'), ' like im_log');
PREPARE stmt1 FROM @sqlStr; EXECUTE stmt1;
END;
-- sqlStr
select CONCAT('create table im_log_', DATE_FORMAT(date_add(curdate(),interval 1 day), '%Y%m%d'), ' like im_log');
-- 运行结果: create table im_log_20230819 like im_log
-- 跨月
select CONCAT('create table im_log_', DATE_FORMAT(date_add(curdate(),interval 20 day), '%Y%m%d'), ' like im_log');
-- 运行结果:create table im_log_20230907 like im_log
修改后使用date_sub()或者是date_add()函数配合curdate()函数使用,可以解决单独使用curdate()函数时间计算的坑(看到很多帖子推荐使用curdate()+1或curdate()+n。
curdate()的本身就是获取当前日期的函数,所以不能直接进行运算,如果需要做日期计算需要配合其他函数共同使用。
curdate()函数与current_date()函数一样的本次只以curdate()函数作为例子。
-- 直接使用current_date()
select current_date()+100, current_date()/2, current_date()*2;
-- 运行结果:20230918,10115409.0000,40461636
结束语
以上就是本次踩坑经历了,希望大家日后工作零bug,生活顺心。欢迎随时交流踩坑心得,共同进步。