MySQL手册中有介绍。

通常我只是转储数据库并用一个新名称重新导入它。这不是非常大的数据库的一个选项。重命名数据库| SCHEMA} db_name TO new_db_name做坏事,只存在于少数版本中,总的来说是个坏主意。

这需要与InnoDB一起工作,InnoDB存储的东西与MyISAM非常不同。


当前回答

简单的方法

切换到数据库目录:

cd /var/lib/mysql/

关闭MySQL…这很重要!

/etc/init.d/mysql stop

好吧,这种方法不适用于InnoDB或BDB-Databases。

重命名数据库:

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数据库。在这种情况下,您必须转储数据库并重新导入它。

其他回答

你不能这么做是有原因的。(尽管有很多尝试的答案)

基本的答案在许多情况下都有效,但在其他情况下会导致数据损坏。 需要根据对数据库的启发式分析来选择策略。 这就是实现这个特性,然后又删除它的原因。(医生)

您需要转储该数据库中的所有对象类型,创建新命名的对象类型,然后导入转储。如果这是一个正常的系统,你得把它关掉。如果不能,则需要设置从此数据库到新数据库的复制。

如果您想查看可以执行此操作的命令,@satishD提供了详细信息,其中传达了一些挑战,您需要围绕这些挑战构建与目标数据库匹配的策略。

你可以使用这个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

简单的方法

切换到数据库目录:

cd /var/lib/mysql/

关闭MySQL…这很重要!

/etc/init.d/mysql stop

好吧,这种方法不适用于InnoDB或BDB-Databases。

重命名数据库:

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数据库。在这种情况下,您必须转储数据库并重新导入它。

有两种方法:

方法1:一个著名的重命名数据库模式的方法是使用Mysqldump转储模式并将其恢复到另一个模式中,然后删除旧的模式(如果需要)。

从壳

 mysqldump emp > emp.out
 mysql -e "CREATE DATABASE employees;"
 mysql employees < emp.out 
 mysql -e "DROP DATABASE emp;"

虽然上面的方法很简单,但它是时间和空间消耗。如果模式大于100GB怎么办?有一些方法可以将上述命令连接在一起以节省空间,但这不会节省时间。

为了纠正这种情况,有另一种重命名模式的快速方法,但是在执行时必须小心。

方法2:MySQL在重命名表方面有一个非常好的特性,甚至可以跨不同的模式工作。这个重命名操作是原子的,在重命名表时没有其他人可以访问它。这只需要很短的时间就可以完成,因为更改表名或表的模式只是元数据的更改。下面是重命名的过程方法:

使用所需的名称创建新的数据库模式。 使用MySQL的" Rename TABLE "命令将旧模式的表重命名为新模式。 删除旧的数据库模式。 如果模式中有视图、触发器、函数、存储过程,也需要重新创建它们。如果表上存在触发器,MySQL的“RENAME TABLE”将失败。为了解决这个问题,我们可以做以下事情:

1)将触发器、事件和存储的例程转储到单独的文件中。在mysqldump命令中使用-E, -R标志(以及转储触发器的-t -d)。一旦触发器被转储,我们将需要从模式中删除它们,以便RENAME TABLE命令能够工作。

 $ mysqldump <old_schema_name> -d -t -R -E > stored_routines_triggers_events.out

2)生成一个只有“BASE”表的列表。可以通过对information_schema的查询找到这些参数。表的表。

 mysql> select TABLE_NAME from information_schema.tables where 
    table_schema='<old_schema_name>' and TABLE_TYPE='BASE TABLE';

3)在输出文件中转储视图。视图可以使用同一个information_schema上的查询来找到。表的表。

mysql> select TABLE_NAME from information_schema.tables where 
   table_schema='<old_schema_name>' and TABLE_TYPE='VIEW';
 $ mysqldump <database> <view1> <view2> … > views.out

4)删除old_schema中当前表上的触发器。

mysql> DROP TRIGGER <trigger_name>;
...

5)在步骤#2中发现的所有“Base”表重命名后恢复上述转储文件。

mysql> RENAME TABLE <old_schema>.table_name TO <new_schema>.table_name;
...
$ mysql <new_schema> < views.out
$ mysql <new_schema> < stored_routines_triggers_events.out

Intricacies with above methods : We may need to update the GRANTS for users such that they match the correct schema_name. These could fixed with a simple UPDATE on mysql.columns_priv, mysql.procs_priv, mysql.tables_priv, mysql.db tables updating the old_schema name to new_schema and calling “Flush privileges;”. Although “method 2″ seems a bit more complicated than the “method 1″, this is totally scriptable. A simple bash script to carry out the above steps in proper sequence, can help you save space and time while renaming database schemas next time.

Percona Remote DBA团队写了一个名为“rename_db”的脚本,其工作方式如下:

[root@dba~]# /tmp/rename_db
rename_db <server> <database> <new_database>

为了演示这个脚本的使用,使用了一个示例模式“emp”,创建测试触发器,在该模式上存储例程。将尝试使用脚本重命名数据库模式,与耗时的转储/还原方法相比,重命名数据库模式需要几秒钟的时间。

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| emp                |
| mysql              |
| performance_schema |
| test               |
+--------------------+


[root@dba ~]# time /tmp/rename_db localhost emp emp_test
create database emp_test DEFAULT CHARACTER SET latin1
drop trigger salary_trigger
rename table emp.__emp_new to emp_test.__emp_new
rename table emp._emp_new to emp_test._emp_new
rename table emp.departments to emp_test.departments
rename table emp.dept to emp_test.dept
rename table emp.dept_emp to emp_test.dept_emp
rename table emp.dept_manager to emp_test.dept_manager
rename table emp.emp to emp_test.emp
rename table emp.employees to emp_test.employees
rename table emp.salaries_temp to emp_test.salaries_temp
rename table emp.titles to emp_test.titles
loading views
loading triggers, routines and events
Dropping database emp

real    0m0.643s
user    0m0.053s
sys     0m0.131s


mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| emp_test           |
| mysql              |
| performance_schema |
| test               |
+--------------------+

正如您在上面的输出中看到的,数据库模式“emp”在不到一秒钟的时间内就被重命名为“emp_test”。最后,这是来自Percona的脚本,上面用于“方法2″”。

#!/bin/bash
# Copyright 2013 Percona LLC and/or its affiliates
set -e
if [ -z "$3" ]; then
    echo "rename_db <server> <database> <new_database>"
    exit 1
fi
db_exists=`mysql -h $1 -e "show databases like '$3'" -sss`
if [ -n "$db_exists" ]; then
    echo "ERROR: New database already exists $3"
    exit 1
fi
TIMESTAMP=`date +%s`
character_set=`mysql -h $1 -e "show create database $2\G" -sss | grep ^Create | awk -F'CHARACTER SET ' '{print $2}' | awk '{print $1}'`
TABLES=`mysql -h $1 -e "select TABLE_NAME from information_schema.tables where table_schema='$2' and TABLE_TYPE='BASE TABLE'" -sss`
STATUS=$?
if [ "$STATUS" != 0 ] || [ -z "$TABLES" ]; then
    echo "Error retrieving tables from $2"
    exit 1
fi
echo "create database $3 DEFAULT CHARACTER SET $character_set"
mysql -h $1 -e "create database $3 DEFAULT CHARACTER SET $character_set"
TRIGGERS=`mysql -h $1 $2 -e "show triggers\G" | grep Trigger: | awk '{print $2}'`
VIEWS=`mysql -h $1 -e "select TABLE_NAME from information_schema.tables where table_schema='$2' and TABLE_TYPE='VIEW'" -sss`
if [ -n "$VIEWS" ]; then
    mysqldump -h $1 $2 $VIEWS > /tmp/${2}_views${TIMESTAMP}.dump
fi
mysqldump -h $1 $2 -d -t -R -E > /tmp/${2}_triggers${TIMESTAMP}.dump
for TRIGGER in $TRIGGERS; do
    echo "drop trigger $TRIGGER"
    mysql -h $1 $2 -e "drop trigger $TRIGGER"
done
for TABLE in $TABLES; do
    echo "rename table $2.$TABLE to $3.$TABLE"
    mysql -h $1 $2 -e "SET FOREIGN_KEY_CHECKS=0; rename table $2.$TABLE to $3.$TABLE"
done
if [ -n "$VIEWS" ]; then
    echo "loading views"
    mysql -h $1 $3 < /tmp/${2}_views${TIMESTAMP}.dump
fi
echo "loading triggers, routines and events"
mysql -h $1 $3 < /tmp/${2}_triggers${TIMESTAMP}.dump
TABLES=`mysql -h $1 -e "select TABLE_NAME from information_schema.tables where table_schema='$2' and TABLE_TYPE='BASE TABLE'" -sss`
if [ -z "$TABLES" ]; then
    echo "Dropping database $2"
    mysql -h $1 $2 -e "drop database $2"
fi
if [ `mysql -h $1 -e "select count(*) from mysql.columns_priv where db='$2'" -sss` -gt 0 ]; then
    COLUMNS_PRIV="    UPDATE mysql.columns_priv set db='$3' WHERE db='$2';"
fi
if [ `mysql -h $1 -e "select count(*) from mysql.procs_priv where db='$2'" -sss` -gt 0 ]; then
    PROCS_PRIV="    UPDATE mysql.procs_priv set db='$3' WHERE db='$2';"
fi
if [ `mysql -h $1 -e "select count(*) from mysql.tables_priv where db='$2'" -sss` -gt 0 ]; then
    TABLES_PRIV="    UPDATE mysql.tables_priv set db='$3' WHERE db='$2';"
fi
if [ `mysql -h $1 -e "select count(*) from mysql.db where db='$2'" -sss` -gt 0 ]; then
    DB_PRIV="    UPDATE mysql.db set db='$3' WHERE db='$2';"
fi
if [ -n "$COLUMNS_PRIV" ] || [ -n "$PROCS_PRIV" ] || [ -n "$TABLES_PRIV" ] || [ -n "$DB_PRIV" ]; then
    echo "IF YOU WANT TO RENAME the GRANTS YOU NEED TO RUN ALL OUTPUT BELOW:"
    if [ -n "$COLUMNS_PRIV" ]; then echo "$COLUMNS_PRIV"; fi
    if [ -n "$PROCS_PRIV" ]; then echo "$PROCS_PRIV"; fi
    if [ -n "$TABLES_PRIV" ]; then echo "$TABLES_PRIV"; fi
    if [ -n "$DB_PRIV" ]; then echo "$DB_PRIV"; fi
    echo "    flush privileges;"
fi

如果您使用分层视图(视图从其他视图中提取数据),从mysqldump导入原始输出可能无法工作,因为mysqldump不关心视图的正确顺序。因此,我编写了脚本,重新排序视图,以纠正飞行中的顺序。

它是这样的:

#!/usr/bin/env perl

use List::MoreUtils 'first_index'; #apt package liblist-moreutils-perl
use strict;
use warnings;


my $views_sql;

while (<>) {
    $views_sql .= $_ if $views_sql or index($_, 'Final view structure') != -1;
    print $_ if !$views_sql;
}

my @views_regex_result = ($views_sql =~ /(\-\- Final view structure.+?\n\-\-\n\n.+?\n\n)/msg);
my @views = (join("", @views_regex_result) =~ /\-\- Final view structure for view `(.+?)`/g);
my $new_views_section = "";
while (@views) {
    foreach my $view (@views_regex_result) {
        my $view_body = ($view =~ /\/\*.+?VIEW .+ AS (select .+)\*\/;/g )[0];
        my $found = 0;
        foreach my $view (@views) {
            if ($view_body =~ /(from|join)[ \(]+`$view`/) {
                $found = $view;
                last;
            }
        }
        if (!$found) {
            print $view;
            my $name_of_view_which_was_not_found = ($view =~ /\-\- Final view structure for view `(.+?)`/g)[0];
            my $index = first_index { $_ eq $name_of_view_which_was_not_found } @views;
            if ($index != -1) {
                splice(@views, $index, 1);
                splice(@views_regex_result, $index, 1);
            }
        }
    }
}

用法: mysqldump -u username -v olddatabase -p | ./mysqldump_view_reorder.pl | mysql -u username -p -D newdatabase .pl