匹配通配符的删除MySQL数据库?

62

我正在运行mySQL,需要在服务器上删除大量的数据库(在对服务器进行测试后)。所有需要删除的数据库都具有相同的前缀“ Whatever_”。

前缀之后,名称是随机的,例如Whatever_something, Whatever_232, Whatever_blabla, .... , Whatever_imthelast。

我将会频繁执行此任务,所以想知道最好的方法是什么?

编辑: 我可以使用任何类型的mysql语言或插件...所以我们有几种方法可以做到这一点。现在,我要求生成数据库的人给我一个每行包含一个数据库名的.txt文件...因此,我正在编写一个快速PHP代码来读取该文件并删除其中的所有数据库,稍后我将尝试百分号答案(如果它有效,则肯定是更容易的方法)。无论如何,我希望以更简单的方式完成此操作,因为我将无法支持此代码(其他人将支持,您懂的...)。

编辑2: 通配符的使用不起作用:#1008-无法删除数据库“whatever _%”;数据库不存在。

11个回答

89
基本思路是在数据库中运行 "show tables" 命令,然后使用其结果选择所需的表。我不认为 MySQL 允许你对 "show tables" 的结果集进行任何操作,但我可能是错误的。
以下是一种使用 shell 的快速、简单解决方案:
mysql -u your_user -D your_database_name -e "show tables" -s | 
  egrep "^Whatever_" | 
  xargs -I "@@" echo mysql -u your_user -D your_database_name -e "DROP TABLE @@"

这将打印出所有以“Whatever_”开头的表的Shell命令。如果你想要实际执行这些命令,请删除单词“echo”。

编辑:我忘了解释上面的内容!我不知道您对shell脚本有多熟悉,但是下面是解释:

mysql -u your_user -D your_database_name -e "show tables" -s

打印出所有表的列表,表头为 "Tables_in_your_database_name"。该输出结果被管道连接到下一个命令:

egrep "^Whatever_"

搜索以单词"Whatever_"开头的任何行,并仅打印这些行。最后,我们通过命令将那个"Whatever_*" 表格列表进行处理:

xargs -I "@@" echo mysql -u your_user -D your_database_name -e "DROP TABLE @@"

循环遍历表名列表的每一行,并将其插入到命令中的“@@”位置。

echo mysql -u your_user -D your_database_name -e "DROP TABLE @@"

所以如果你有一堆名为"Whatever_1"、"Whatever_2"、"Whatever_3"的表格,生成的命令将会是:

echo mysql -u your_user -D your_database_name -e "DROP TABLE Whatever_1"
echo mysql -u your_user -D your_database_name -e "DROP TABLE Whatever_2"
echo mysql -u your_user -D your_database_name -e "DROP TABLE Whatever_3"

哪种方法会输出以下内容:

mysql -u your_user -D your_database_name -e "DROP TABLE Whatever_1"
mysql -u your_user -D your_database_name -e "DROP TABLE Whatever_2"
mysql -u your_user -D your_database_name -e "DROP TABLE Whatever_3"

我希望提供的内容足够详细,而不是给任何人带来过多的信息。祝好运,并在使用“DROP TABLE”命令时小心!


使用您的精确Bash脚本,我的输出中没有引号(")后面的内容。它会输出这样的行:mysql -u root -D joomla_test -e DROP TABLE bak_xlr1q_weblinks。我正在使用Bash 4.1.5(1)-release版本。 - Hubro
@Codemonkey 为了让引号出现,你可以进行转义。将 "DROP TABLE @@" 替换为 \"DROP TABLE @@\" - Shalom Craimer
很棒的答案!您可以考虑使用printf而不是echo,以避免引号等方面的不一致行为。但这只是小问题 :) - Anders Martini

38

scraimer 的回答原则是正确的,但因为问题是关于删除数据库而不是数据库中的表格,所以正确的命令应该是:

mysql -u your_username -p'your password' -e 'show databases' 
| grep Whatever_* 
| xargs -I "@@" mysql -u your_username -p'your password' -e "DROP database \`@@\`"

如需了解该命令的解释,请参阅scraimer的解释。

最后一部分是...... \`@@\` 我们用反引号(`)引用了我们的结果数据库名称,以防我们的数据库名称包含像“-”这样的特殊字符

干杯


对我来说,在grep部分使用正则表达式更好:| grep -e ".*_backup" 选择所有以“_backup”结尾的数据库。 - Yeti
1
对于任何人将此内容复制粘贴到其终端中,请在命令前加上一个空格。这样可以避免在命令历史记录中存储该命令(包括您的密码明文!)。 - KlaymenDK

15
我们可以使用存储过程来实现。下面是一个存储过程的示例:
drop procedure if exists droplike;
delimiter //
create procedure droplike(pattern varchar(20))
begin
  set group_concat_max_len = 65535;
  select @drop:= concat( 'drop table ', group_concat(table_name) , ';' ) from information_schema.tables where table_schema = "database_name" and table_name like pattern;
  prepare statement from @drop;
  execute statement;
end //
delimiter ;

用数据库的名字替换database_name(需要写入权限)。为了删除符合XYZ模式的表格,调用以下输入为XYZ后跟通配符的过程:

call droplike("XYZ%");

一些SQL方言允许使用逗号分隔的列表,例如:DROP TABLE "table1_bits", "table2_links", "table3_stuff"; - MarkHu

5

这里有一些不错的整洁解决方案。但是我所做的只是:

SHOW TABLES LIKE 'migrate%';

在MySQL Workbench中。

然后我将结果复制到一个可以使用转义序列查找/替换的好文本编辑器中,并用\n替换为;\nDROP TABLE ,并整理了开头和结尾。然后再次复制回MySQL Workbench。这种方法比一些提出的解决方案更加手动且不太优雅,但实际上同样快速。


1

我认为在MySql中无法删除多个数据库。

但是我有一个非常极客的解决方案。您可以使用C/C++/C#/JAVA编程,将"DROP DATABASE WHATEVER_<name>;"打印多次到记事本或任何文本编辑器中。之后,您可以将其复制粘贴到MySql的客户端命令提示符中,然后完成操作。不要忘记在每个DROP命令后加上 ";"。

我相信这是可行的。请尝试编写此代码。


1
这个(Jython)怎么样?
rs = stmt.executeQuery( "SHOW DATABASES LIKE 'Whatever_%'" )
databases_for_dropping = []
while rs.next():
  databases_for_dropping.append( rs.getString( 1 ))
for database_for_dropping in databases_for_dropping:
  stmt.execute( "DROP DATABASE %s" % database_for_dropping ) 

0
如果有人正在寻找一个简单的答案,与scraimer和Explorer相似,但是使用JDBC编写Java代码(就像我一样),这里有一个快速而且简单的方法,它可以为我完成工作:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

public class DatabaseDeleter {
    // Pass your database wildcard as the only argument to program ( "%MY_CRAZY_PATTERN%")
    public void main(String[] args) throws SQLException, ClassNotFoundException{

        Class.forName("com.mysql.jdbc.Driver");
        Connection connection = DriverManager.getConnection("jdbc:mysql://databaseURL");
        PreparedStatement pst = connection.prepareStatement("show databases like ?");
        pst.setString(1, args[0]);
        ResultSet rs = pst.executeQuery();

        ArrayList<String> databases = new ArrayList<String>();
        while (rs.next()) databases.add(rs.getString(1));

        for (String s : databases){
            Statement st = connection.createStatement();
            st.execute("drop database " + s);
        }
        connection.close();
    }
}

警告:如果您不想让您的SQL服务器被攻击,请不要向客户甚至其他开发人员公开此信息。


-1

抱歉,我们无法使用SQL命令一次删除多个数据库


-5
你可以尝试使用mysql 5通用例程库(可从这里下载)。使用它,您可以删除与正则表达式匹配的多个表。建议仔细检查正则表达式,以防删除您需要的表。

我认为你没有完整地阅读问题。他想要删除多个“数据库”,而不是多个“表”。 - Xn0vv3r

-5
DROP DATABASE `any-database_name`;

我只是在我的数据库名称前后使用这个字符`(反引号)。


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