在MySQL存储过程中,如果临时表的结构或表名需要在运行时决定,可以通过PREPARE语句动态拼接CREATE TABLE来实现。这种方式适合处理按参数生成不同临时表的场景。

为什么需要动态创建临时表
普通存储过程里写的CREATE TEMPORARY TABLE是静态SQL,表名和字段在编译时就固定了。当业务要求根据传入的日期、类型编号动态建表时,静态写法无法满足条件。利用PREPARE可以把SQL字符串拼出来再执行,从而突破这个限制。
基本语法与实现步骤
核心思路是:用CONCAT把表名和字段定义拼成完整SQL,放进用户变量,再用PREPARE和EXECUTE执行。
DELIMITER //
CREATE PROCEDURE dyn_tmp_table(IN tbl_suffix VARCHAR(20))
BEGIN
DECLARE sql_str VARCHAR(1000);
-- 拼接临时表创建语句
SET sql_str = CONCAT(
'CREATE TEMPORARY TABLE tmp_', tbl_suffix, ' (',
'id INT PRIMARY KEY, ',
'name VARCHAR(50) ',
')'
);
-- 预备语句
SET @create_sql = sql_str;
PREPARE stmt FROM @create_sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;
调用示例
调用上述过程即可生成对应的临时表:
CALL dyn_tmp_table('202401');
-- 此时已创建临时表 tmp_202401
INSERT INTO tmp_202401 VALUES (1, '测试');
SELECT * FROM tmp_202401;
注意事项
- PREPARE只能执行用户变量或存储过程内的字符串,不能直接执行局部DECLARE变量,因此要用SET @var = 局部变量转换。
- 临时表在当前连接会话中有效,连接断开后自动销毁,适合中间计算。
- 表名拼接要防止SQL注入,生产环境应校验输入参数格式。
- 同一个会话中不能重复创建同名的临时表,再次调用前可用DROP TEMPORARY TABLE IF EXISTS清理。
带清理的完整写法
DELIMITER //
CREATE PROCEDURE safe_dyn_tmp(IN suffix VARCHAR(20))
BEGIN
SET @drop_sql = CONCAT('DROP TEMPORARY TABLE IF EXISTS tmp_', suffix);
PREPARE d FROM @drop_sql;
EXECUTE d;
DEALLOCATE PREPARE d;
SET @crt = CONCAT('CREATE TEMPORARY TABLE tmp_', suffix, ' (id INT)');
PREPARE c FROM @crt;
EXECUTE c;
DEALLOCATE PREPARE c;
END //
DELIMITER ;
通过上述方式,开发者可以在MySQL存储过程中利用PREPARE拼接CREATE TABLE,灵活地完成动态临时表的创建与管理。