MySQL自动导出文件实战:动态SQL+事件调度器定时备份详细代码注释

张开发
2026/4/8 22:18:57 15 分钟阅读

分享文章

MySQL自动导出文件实战:动态SQL+事件调度器定时备份详细代码注释
更多数据分析干货关注公众号船长Talk每天分享SQL / Python / 数据分析实战技巧MySQL 自动导出文件实战用事件调度器动态SQL实现定时备份详细代码注释在数据分析工作中有一个痛点很多人都遇到过手动导出数据费时费力每天早上9点前要把昨天的数据导出来稍微一忘就迟到了……今天船长来分享一个 MySQL 自动化导出方案利用CONCATPREPAREEXECUTE动态SQL结合 MySQL 事件调度器实现定时自动导出文件文件名自带时间戳。直接上代码每一行都有注释。一、核心思路-- 公众号船长Talk -- 思路不能直接把变量塞进INTO OUTFILE所以要用动态SQL -- 步骤 -- 1. 用 CONCAT 把导出语句字符串拼出来把时间戳嵌进文件名 -- 2. 用 PREPARE 把这个字符串编译成可执行语句 -- 3. 用 EXECUTE 执行它为什么要动态SQL因为 MySQL 的INTO OUTFILE后面接的文件路径必须是字符串字面量不能直接用变量。 所以要先把整个 SELECT 语句拼成字符串再让 MySQL 去执行这个字符串。二、方案一单次执行手动触发2.1 基础版导出学生成绩表-- 公众号船长Talk -- 功能导出 sc学生选课表文件名带Unix时间戳逗号分隔 -- Step 1拼接导出语句字符串 SET str_name CONCAT( SELECT * INTO OUTFILE C:/ProgramData/MySQL/MySQL Server 5.7/Uploads/, UNIX_TIMESTAMP(NOW()), -- 时间戳如1576218000 .txt , FIELDS TERMINATED BY , , -- 字段用逗号分隔 LINES TERMINATED BY \\r\\n , -- 行用 CRLF 分隔Windows友好 FROM (, SELECT 学号,课程号,分数 , -- 第1行表头 UNION ALL , SELECT * FROM sc, -- 数据行 ) AS a ); -- Step 2查看拼接结果调试用确认语句正确再执行 SELECT str_name; -- Step 3编译动态SQL PREPARE translation FROM str_name; -- Step 4执行 EXECUTE translation; -- Step 5释放资源好习惯 DEALLOCATE PREPARE translation;执行后效果生成类似1576218000.txt的文件内容学号,课程号,分数 001,C01,90 001,C02,85 002,C01,78 ...2.2 进阶版带日期格式文件名-- 公众号船长Talk -- 改进文件名用 DATE_FORMAT 生成易读的日期格式如 20191213.txt SET str_name CONCAT( SELECT * INTO OUTFILE C:/ProgramData/MySQL/MySQL Server 5.7/Uploads/sc_, DATE_FORMAT(NOW(), %Y%m%d), -- 格式20191213 .txt , FIELDS TERMINATED BY , , LINES TERMINATED BY \\r\\n , FROM sc ); SELECT str_name; -- 调试确认路径和语句 PREPARE stmt FROM str_name; EXECUTE stmt; DEALLOCATE PREPARE stmt;三、方案二封装成存储过程每次手动执行太麻烦封装成存储过程一个CALL搞定。-- 公众号船长Talk -- 创建存储过程导出任意表到带时间戳的文件 DELIMITER $$ CREATE PROCEDURE export_to_file( IN table_name VARCHAR(64), -- 表名输入参数 IN export_dir VARCHAR(255) -- 导出目录输入参数 ) BEGIN -- 声明变量 DECLARE v_sql VARCHAR(1000); DECLARE v_filename VARCHAR(255); -- 拼文件名目录 表名 日期 .csv SET v_filename CONCAT( export_dir, table_name, _, DATE_FORMAT(NOW(), %Y%m%d_%H%i%s), -- 精确到秒 .csv ); -- 拼SQL语句 SET v_sql CONCAT( SELECT * INTO OUTFILE , v_filename, , FIELDS TERMINATED BY , , OPTIONALLY ENCLOSED BY \ , -- 字段值用双引号包裹 LINES TERMINATED BY \\n , FROM , table_name ); -- 执行 SET dynamic_sql v_sql; PREPARE stmt FROM dynamic_sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; -- 输出确认信息 SELECT CONCAT(✅ 导出完成, v_filename) AS result; END $$ DELIMITER ; -- 使用示例 CALL export_to_file(student, C:/ProgramData/MySQL/MySQL Server 5.7/Uploads/); CALL export_to_file(sc, C:/ProgramData/MySQL/MySQL Server 5.7/Uploads/);四、方案三事件调度器Event Scheduler实现定时自动导出这才是自动化的核心MySQL 的 Event Scheduler 类似 Linux 的 crontab可以定时执行 SQL 任务。4.1 先开启事件调度器-- 公众号船长Talk -- 查看事件调度器状态 SHOW VARIABLES LIKE event_scheduler; -- 临时开启重启后失效 SET GLOBAL event_scheduler ON; -- 永久开启在 my.cnf / my.ini 中加入 -- [mysqld] -- event_scheduler ON4.2 创建定时导出事件-- 公众号船长Talk -- 每天凌晨2点自动导出 student 表 DELIMITER $$ CREATE EVENT IF NOT EXISTS daily_export_student ON SCHEDULE EVERY 1 DAY -- 每天执行一次 STARTS 2024-01-01 02:00:00 -- 从这个时间点开始 DO BEGIN -- 拼接动态SQL文件名带日期 SET fileName CONCAT( SELECT * INTO OUTFILE C:/ProgramData/MySQL/MySQL Server 5.7/Uploads/student_, DATE_FORMAT(NOW(), %Y%m%d), .csv , FIELDS TERMINATED BY , , OPTIONALLY ENCLOSED BY \\ , LINES TERMINATED BY \\n , FROM student ); -- 执行动态SQL PREPARE stmt FROM fileName; EXECUTE stmt; DEALLOCATE PREPARE stmt; END $$ DELIMITER ;4.3 查看和管理事件-- 公众号船长Talk -- 查看所有事件 SHOW EVENTS; -- 查看特定数据库的事件 SHOW EVENTS FROM my_database; -- 临时禁用事件 ALTER EVENT daily_export_student DISABLE; -- 重新启用事件 ALTER EVENT daily_export_student ENABLE; -- 删除事件 DROP EVENT IF EXISTS daily_export_student;五、触发器数据写入时自动触发导出除了定时任务还有一种场景每次数据更新后立刻触发导出。用触发器Trigger来实现。-- 公众号船长Talk -- 场景banzhuren 表插入数据时自动向 bumenbiao 同步主键 -- bumenbiao 表主键为 id -- banzhuren 表外键为 departmentid关联 bumenbiao.id -- 创建触发器 CREATE TRIGGER sync_department BEFORE INSERT ON banzhuren -- 在 banzhuren 表插入前触发 FOR EACH ROW -- 对每一行都执行 BEGIN -- 先往部门表插入对应的 id保证外键完整性 INSERT INTO bumenbiao(id) VALUES (NEW.departmentid); -- NEW 关键字代表即将插入的新行数据 END; -- 测试插入 INSERT INTO banzhuren VALUES (5, qwe, 3, 4); -- 查看所有触发器 SHOW TRIGGERS FROM my_database; -- 删除触发器 DROP TRIGGER IF EXISTS sync_department;六、常见报错与解决方案报错信息原因解决方案ERROR 1290: --secure-file-privMySQL限制了导出目录用SHOW VARIABLES LIKE secure_file_priv查看允许路径把文件导到那个目录ERROR 1086: File already exists同名文件已存在文件名加上精确到秒的时间戳%H%i%s确保唯一性ERROR 1227: Access denied用户没有FILE权限GRANT FILE ON *.* TO userlocalhost;事件不执行事件调度器未开启SET GLOBAL event_scheduler ON;七、总结这套方案的核心是动态SQL三连击CONCAT拼语句 →PREPARE编译 →EXECUTE执行文件名带时间戳UNIX_TIMESTAMP(NOW())或DATE_FORMAT(NOW(), %Y%m%d)自动化选项存储过程手动调用/ 事件调度器定时/ 触发器数据变更时掌握这套技巧再也不用每天手动导数据了。船长 Tipssecure_file_priv是很多同学卡住的第一道关先SHOW VARIABLES LIKE secure_file_priv确认路径把导出目录改到允许的路径就行了。 觉得有用关注公众号船长Talk每天分享 SQL / Python / 数据分析干货帮你少踩坑、多涨薪

更多文章