一、MySQL 重命名表

语法

-- 方式1(通用)
ALTER TABLE 旧表名 RENAME TO 新表名;

-- 方式2(跨库也可用,推荐)
RENAME TABLE 旧表名 TO 新表名;

示例

原表 user,改名为 user_old

ALTER TABLE `user` RENAME TO `user_old`;

二、复制原表结构(空表,仅结构、索引、字段,不复制数据

-- 语法
CREATE TABLE 新表名 LIKE 源表名;

-- 示例:创建和 user_old 结构完全一致的新表 user
CREATE TABLE `user` LIKE `user_old`;

三、如果需要连数据一起复制(结构+数据全量克隆)

-- 结构 + 数据 一起复制
CREATE TABLE 新表名 SELECT * FROM 源表名;

完整流程示例(常用场景:旧表改名 + 新建同结构空表)

-- 1. 把原有业务表改名备份
ALTER TABLE `test_table` RENAME TO `test_table_bak`;

-- 2. 创建一张和原表结构完全相同的新空表
CREATE TABLE `test_table` LIKE `test_table_bak`;

补充说明

  1. LIKE 方式会完整复制字段、数据类型、主键、索引、默认值、注释,不会复制数据;
  2. 执行前建议先锁表/停业务,避免数据写入导致不一致;
  3. 表名建议用反引号 ` 包裹,防止和关键字冲突。

关于 ALTER TABLE 和 RENAME TABLE 这两种语法的区别,速度和原理是否一样:

-- 方式1(通用)
ALTER TABLE 旧表名 RENAME TO 新表名;

-- 方式2(跨库也可用,推荐)

两种表改名语法:区别、原理、速度

一、核心结论

底层原理、执行速度基本一致,都是元数据级操作(瞬间完成,不改动表数据),主要差异在语法能力、使用场景、语法规范


二、详细区别

1. 语法与标准归属

  1. ALTER TABLE 旧名 RENAME TO 新名

    • 属于 ALTER TABLE 子语法,是 SQL 标准衍生写法。
    • 仅支持单表改名不能跨数据库
    • 语法语义:修改表的名称属性。
  2. RENAME TABLE 旧名 TO 新名

    • MySQL 专属扩展语法,功能更强。
    • 支持单表 / 多表批量改名跨数据库迁移表
    • 多表示例:

      RENAME TABLE t1 TO t1_bak, t2 TO t2_bak;
    • 跨库示例(把 db1.tbl 移到 db2 并重命名):

      RENAME TABLE db1.tbl TO db2.tbl_new;

2. 权限要求

  • 两者都需要原表的 ALTER 权限。
  • 跨库使用 RENAME TABLE 时,需要目标库的 CREATE 权限

3. 锁机制 & 并发(InnoDB)

两者在 InnoDB 下行为一致:

  • 均为元数据操作,仅修改数据字典、文件映射,不拷贝行数据
  • 执行时会加 MDL 元数据锁,短时间阻塞 DDL/DML,锁持有时间极短。
  • 不存在 IO 读写,速度完全相同,都是毫秒级。

4. 兼容性

  • ALTER TABLE ... RENAME:兼容更多数据库(MariaDB、部分其他SQL库),通用性更好。
  • RENAME TABLE纯 MySQL 专用,其他数据库不识别。

三、原理(完全一致)

MySQL 表名本质只是数据字典里的标识,同时对应磁盘上 .frm.ibd 等文件名称:

  1. 两种语法都不遍历、不迁移表内数据
  2. 仅修改:数据字典记录 + 磁盘上表相关文件名称;
  3. InnoDB 共享表空间/独立表空间,行为无区别。

四、使用场景建议

  1. 同库、单表、追求通用兼容 → 用 ALTER TABLE ... RENAME TO
  2. 跨库、批量改表名、MySQL 专属环境 → 优先 RENAME TABLE
  3. 速度不用纠结:二者性能无差异
    RENAME TABLE 旧表名 TO 新表名;

实战:备份日志表并创建新的日志表,用到变量、动态SQL执行

-- 定义变量:拼接 表名_年月日
SET @old_tb = 'sp_log';
SET @suffix = DATE_FORMAT(CURDATE(), '%Y%m%d');
SET @bak_tb = CONCAT(@old_tb, '_', @suffix);

-- 2. 第一条:重命名旧表
SET @sql1 = CONCAT('RENAME TABLE `', @old_tb, '` TO `', @bak_tb, '`;');
PREPARE stmt1 FROM @sql1;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;

-- 3. 第二条:新建同结构空表
SET @sql2 = CONCAT('CREATE TABLE `', @old_tb, '` LIKE `', @bak_tb, '`;');
PREPARE stmt2 FROM @sql2;
EXECUTE stmt2;
DEALLOCATE PREPARE stmt2;

如果你尝试将两条SQL放到一个预定义语句中执行,将喜提一个报错:
报错原因
MySQL 一条预处理语句里不能同时放两条独立 SQL(RENAME + CREATE 写在同一个字符串里),解析时直接语法报错。
预处理 PREPARE 单次只支持单条 SQL 语句。

  SET @sql = CONCAT(
    'RENAME TABLE `', @old_tb, '` TO `', @bak_tb, '`;',
    'CREATE TABLE `', @old_tb, '` LIKE `', @bak_tb, '`;'
  );

  PREPARE stmt FROM @sql;
  EXECUTE stmt;
  DEALLOCATE PREPARE stmt;

标签: none

添加新评论