如何重命名MySQL数据库(更改模式名称)?

1141

5
还有在Serverfault上的讨论:http://serverfault.com/questions/195221/how-to-rename-a-mysql-database - Yves Martin
46个回答

1008

对于InnoDB,以下方法似乎有效:先创建新的空数据库,然后逐个将表重命名到新的数据库中:

RENAME TABLE old_db.table TO new_db.table;

之后您需要调整权限。

若要在shell中编写脚本,可以使用以下任意一种:

mysql -u username -ppassword old_db -sNe 'show tables' | while read table; \ 
    do mysql -u username -ppassword -sNe "rename table old_db.$table to new_db.$table"; done

或者

for table in `mysql -u root -ppassword -s -N -e "use old_db;show tables from old_db;"`; do mysql -u root -ppassword -s -N -e "use old_db;rename table old_db.$table to new_db.$table;"; done;

注意事项:

  • -p选项和密码之间没有空格。如果你的数据库没有密码,删除-u username -ppassword这一部分。
  • 如果某个表有触发器,使用上述方法无法将其移动到另一个数据库(会导致“Trigger in wrong schema”错误)。如果是这种情况,请使用传统的方法克隆一个数据库,然后删除旧数据库:

    mysqldump old_db | mysql new_db

  • 如果你有存储过程,可以在之后复制它们:

    mysqldump -R old_db | mysql new_db


4
如果你的数据库很大但不包含太多表(或者你愿意编写一个脚本来循环所有表),那么这是一个好选择和前进的方式。此外,在InnoDB中,这只是逻辑重命名,在MyISAM中,根据你的文件系统,它可能是逻辑重命名或在磁盘上真正复制数据。 - Pablo Marin-Garcia
37
我刚刚使用InnoDB数据库完成了30多个表的操作,使用了file_per_table设置,尽管有些表格包含3百万以上的行,但它在不到1秒钟内就完成了。它似乎只是移动存储上的文件,而不是执行更复杂的操作... 如果可以的话请加2分 :) - Dave Rix
18
请注意,这对视图无效。您无法重命名视图以使它们从一个数据库跳转到另一个数据库。请改用“DROP VIEW”和“CREATE VIEW”。虽然有些繁琐,但你可能需要在首先移动所有表之后进行“mysqldump”来移动视图。还要注意,“SHOW TABLES”会显示表和视图,请小心。 - tuomassalo
12
同时,这种方法对于带触发器的表是不适用的。在移动表之前,您需要找到、导出和删除触发器,然后将导出的触发器导入目标数据库。 - Olfan
9
已更新(即有效)的链接,记录了为什么“RENAME DATABASE”被移除:http://dev.mysql.com/worklog/task/?id=4030。 - alexis
显示剩余12条评论

503

使用这些简单的命令:

mysqldump -u username -p -v olddatabase > olddbdump.sql
mysqladmin -u username -p create newdatabase
mysql -u username -p newdatabase < olddbdump.sql

或者像@Pablo Marin-Garcia建议的那样,为了减少I/O使用以下方式:

mysqladmin -u username -p create newdatabase
mysqldump -u username -v olddatabase -p | mysql -u username -p -D newdatabase

114
正如原帖所说,"对于非常大的数据库来说,这不是一个选项。" - pilcrow
4
请勿忘记删除原始数据库。 - Pavel Radzivilovsky
4
太棒了!以下是一些建议,以进一步提高此问题的搜索效果:(1)将Pablo Marin-Garcia的代码片段移到顶部,因为它似乎是最佳答案。(2)在每个语句中都加上“-p<password>”,而不是只有“-p”,这样就可以避免出现提示。 - Steve Chambers
10
使用管道版本时,我会得到两个“输入密码:”提示,如下所示:输入密码:输入密码:它似乎只接受一个密码,而不是两个。我是否遗漏了什么细节? - Ryan
43
很惊讶没有人提到这一点,但你真的应该将 --routines 标志添加到 mysqldump 命令中,以确保存储过程也被复制。 - Carlos P
显示剩余3条评论

244

我认为解决方案更简单,一些开发人员已经提出了建议。phpMyAdmin有一个可用于此操作的功能。

从phpMyAdmin中选择要选择的数据库。在选项卡中,有一个名为“操作”的选项,转到重命名部分。就这样。

正如许多人建议的那样,它会创建一个新的数据库,并将旧数据库的所有表转储到新数据库中,然后删除旧数据库。

输入图像描述


97
假设你的环境中已经安装了PHP或者使用了PHPMyAdmin。 - Chris
37
即使您有phpMyAdmin,也很危险——后端可能会在进行过程中失败,导致两个数据库处于未知状态,或者可能需要很长时间,导致前端挂起或PHP超时。 - mozboz
21
没错,@mozboz,但我已经这样做了10年,从来没有遇到过这个问题。如果你通过shell运行命令,电脑崩溃的可能性也是存在的。但这种可能性有多大呢?是1分之1万亿吗? - raphie
32
通过控制台运行的脚本也是一个前端,可能会遇到同样的问题。 - Greg
16
对于涉及大型数据库的情况,控制台操作比PhpMyAdmin更可靠,这正是原帖作者的情况。个人建议在有相当大的数据库时使用任何控制台方法而不是PhpMyAdmin。不用说,在小型数据库上,PhpMyAdmin同样好用。 - Teodor Sandu
显示剩余8条评论

122

你可以使用SQL生成一个SQL脚本,将源数据库中的每个表传输到目标数据库。

在运行从该命令生成的脚本之前,您必须先创建目标数据库。

您可以使用以下两个脚本之一(我最初建议使用前者,但有人“改进”我的答案以使用GROUP_CONCAT。选择其中一个即可,但我更喜欢原来的):

SELECT CONCAT('RENAME TABLE $1.', table_name, ' TO $2.', table_name, '; ')
FROM information_schema.TABLES 
WHERE table_schema='$1';
或者
SELECT GROUP_CONCAT('RENAME TABLE $1.', table_name, ' TO $2.', table_name SEPARATOR '; ')
FROM information_schema.TABLES 
WHERE table_schema='$1';

(假设$1和$2分别是源和目标)

这将生成一条SQL命令,您需要运行该命令。

请注意,GROUP_CONCAT具有默认长度限制,对于具有大量表的数据库可能会超过该限制。 您可以通过运行SET SESSION group_concat_max_len = 100000000;(或其他大数值)来更改该限制。


2
如果表有参照约束,这段代码能正常工作吗?我预计是不行的。 - dolmen

82

模拟在MySQL中缺失的RENAME DATABASE命令:

  1. 创建一个新数据库

  2. 使用以下查询创建重命名语句:

     SELECT CONCAT('RENAME TABLE ',table_schema,'.`',table_name,
         '` TO ','new_schema.`',table_name,'`;')
     FROM information_schema.TABLES
     WHERE table_schema LIKE 'old_schema';
    
  3. 运行输出

  4. 删除旧数据库

这段内容摘自 模拟MySQL中缺失的RENAME DATABASE命令.


1
太好了!我已经测试了InnoDB和MyISAM表。这是我测试过的最快的解决方案(重命名表几乎是瞬间完成,没有延迟)! - Philipp
太好了!只要记得之后修复权限就行。 - Navidot
请注意,在处理实时数据库时,请在运行重命名查询之前进行此操作。 - Navidot
1
如果表具有引用约束,这是否有效?我认为不会。 - dolmen
这是一个很好的解决方案,特别是当您不必移动存储过程、触发器和事件时。 - dankilev
它就像魔法一样有效!!! - Shawn Guo

34
您可以使用这个Shell脚本:
参考: 如何重命名MySQL数据库?
#!/bin/bash
set -e # terminate execution on command failure

mysqlconn="mysql -u root -proot"
olddb=$1
newdb=$2
$mysqlconn -e "CREATE DATABASE $newdb"
params=$($mysqlconn -N -e "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES \
                           WHERE table_schema='$olddb'")
for name in $params; do
      $mysqlconn -e "RENAME TABLE $olddb.$name to $newdb.$name";
done;
$mysqlconn -e "DROP DATABASE $olddb"

它正在工作:

$ sh rename_database.sh oldname newname

9
小心处理这个操作。如果你没有使用root用户登录,可能会受到权限限制,导致重命名失败而删除成功,进而导致数据库被删除。除此之外,脚本还不错。 - Lex
5
我在脚本开头添加了set -e,这将导致执行失败时终止程序并应该缓解那个问题。 - Mikkel
在中间的某个地方,我遇到了错误 ERROR 1435 (HY000) 在第1行: 触发器位于错误的模式中 - pymen
@pymen,你能分享一下同样的截图吗? - Grijesh Chauhan

25

三个选项:

  1. 创建新的数据库,停止服务器,将文件从一个数据库文件夹移动到另一个文件夹中,并重新启动服务器。请注意,这仅适用于所有表都是MyISAM格式。

  2. 创建新数据库,使用CREATE TABLE ... LIKE语句,然后使用INSERT ... SELECT * FROM语句。

  3. 使用mysqldump命令导出数据并使用该文件进行恢复。


对于myisam引用,我无法弄清为什么这对我没有起作用。 - Christian Payne
6
问题说明必须适用于InnoDB,而不是MyISAM。 - D-Rock
@D-Rock 告诉谷歌,是他们根据标题把人带到这里的。 - jiggunjer

23

简单方法

切换至数据库目录:

cd /var/lib/mysql/

关闭 MySQL... 这非常重要!

/etc/init.d/mysql stop

好的,这种方法不适用于InnoDB或BDB数据库。

重命名数据库:

mv old-name new-name

...对于表格...

cd database/

mv old-name.frm new-name.frm

mv old-name.MYD new-name.MYD

mv old-name.MYI new-name.MYI

重启MySQL

/etc/init.d/mysql start

完成...

好的,这种方法不适用于InnoDB或BDB数据库。在这种情况下,您必须导出数据库并重新导入它。


23
重命名文件夹会导致某些玩具无法使用。 - ViniciusPires
1
@Rahly,即使设置了每个表一个文件,仍然很危险,除非您确定数据库是在设置该标志之后创建的,否则在设置一个文件每个表之前创建的表将会出现问题。 - user1663023
一般而言,大多数人要么采用一种方式,要么采用另一种方式,不会随意更改是否将每个表格存储于单独文件中。此外,即使在您的情况下,如果先创建了这些表格,它们在第一次默认不会作为单独的文件存在,因此移动不起作用也是安全的,没有危险。请记住,在移动过程进行时,数据库是不运行的。 - Rahly
在OS X上使用Homebrew安装的MySQL等效命令如下:launchctl unload -w ~/Library/LaunchAgents/homebrew.mxcl.mysql.plist cd /usr/local/var/mysql mv old-name new-name launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.mysql.plist - coberlin
小心更改文件夹名称,它可能包含引用旧文件夹的隐藏文件。 - MGE

21

最简单、可靠的重命名方式,包括在最后删除旧数据库,使其成为一个重命名而不是复制操作:

mysqladmin -uroot -pmypassword create newdbname
mysqldump -uroot -pmypassword --routines olddbname | mysql -uroot -pmypassword newdbname
mysqladmin -uroot -pmypassword drop olddbname

步骤:

  1. 将这些行复制到记事本中。
  2. 用您自己的等效内容替换所有对"olddbname"、"newdbname"、"mypassword"(+ 可选 "root")的引用。
  3. 在命令行上逐一执行(在提示时输入"y")。

避免将您的密码添加到控制台中,因为这样不安全。如果您已经这样做,请使用history -cw命令进行删除。相反地,请将密码留空,并在提示后输入密码。 - Tommie C.
它花费的时间异常长,超过20分钟仍未完成。取消操作是否可行? - Sigu Magwa

19

我最近才发现了一种非常好的方法,适用于MyISAM和InnoDB,并且非常快:

RENAME TABLE old_db.table TO new_db.table;

我不记得在哪里看到的,但功劳归于其他人而不是我。


@ArkadijKuzhel 不这么认为。我认为你在谈论RENAME DATABASE。 - Rob Grant
这真的很有帮助,我创建了一个新的空白数据库,然后使用了代码,所有表格都以所需的名称导入。 - Incredible
4
此处存在与被接受答案相同的问题 — "RENAME DATABASE 被发现存在危险,并在 MySQL 5.1.23 中被移除" - 出自 dev.mysql.com/doc/refman/5.1/en/rename-database.html。 - Blake Frederick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接