如何在无存储过程下用带变量的MySQL嵌套查询批量删表?
实现带变量条件的MySQL批量删表(无需存储过程)
现有一段可批量删除数据库表的MySQL Prepared Statements代码(感谢Stack Overflow用户@Devart):
SET @tables = NULL; SET @db='tech'; SET @days = 365; SELECT GROUP_CONCAT(@db, '.`',table_name, '`') INTO @tables FROM (select t.table_name, ifnull(t.UPDATE_TIME, t.CREATE_TIME) update_time from information_schema.tables t) TT; SET @tables = CONCAT('DROP TABLE IF EXISTS ', @tables); SELECT @tables; PREPARE stmt1 FROM @tables; EXECUTE stmt1; DEALLOCATE PREPARE stmt1;
需求是为嵌套SELECT语句添加包含@db、@days变量的WHERE子句,具体条件为:
- 表所属数据库为
@db - 表的最后更新时间(无则取创建时间)早于当前日期减去
@days天 - 表名不匹配
%_delete,或者表名包含数字开头的后缀
尝试过通过CONCAT+PREPARE+EXECUTE拼接动态SQL,但无法将EXECUTE的结果存入变量或嵌套在子查询中,导致代码无法运行,现需在不使用单独存储过程或函数的前提下实现该需求。
解决方案
直接在嵌套SELECT语句中使用用户变量编写WHERE子句即可,无需额外的动态SQL拼接。修改后的完整代码如下:
SET @tables = NULL; SET @db='tech'; SET @days = 365; -- 筛选符合条件的表并拼接成DROP语句格式 SELECT GROUP_CONCAT(@db, '.`',table_name, '`') INTO @tables FROM ( SELECT t.table_name, IFNULL(t.UPDATE_TIME, t.CREATE_TIME) update_time FROM information_schema.tables t WHERE t.table_schema = @db AND IFNULL(t.UPDATE_TIME, t.CREATE_TIME) < CURDATE() - INTERVAL @days DAY AND (TABLE_NAME NOT LIKE '%_delete' OR TABLE_NAME RLIKE '[0-9].*') ) TT; -- 生成并执行DROP TABLE语句 SET @tables = CONCAT('DROP TABLE IF EXISTS ', @tables); SELECT @tables; -- 可选步骤,用于预览即将删除的表 PREPARE stmt1 FROM @tables; EXECUTE stmt1; DEALLOCATE PREPARE stmt1;
关键说明
- MySQL的用户变量(如
@db、@days)可直接在SELECT语句的WHERE子句中引用,无需通过CONCAT拼接SQL字符串 - 通过原生查询直接筛选符合条件的表,避开了动态SQL结果无法嵌套使用的问题
SELECT @tables是可选的预览步骤,可先确认要删除的表是否正确,再执行EXECUTE语句
内容的提问来源于stack exchange,提问作者sFishman
相关产品推荐
相关产品推荐

