MySQL DROP所有表,忽略外键


402

有没有一种很好的简便方法可以从MySQL数据库中删除所有表,而忽略其中可能存在的任何外键约束?


1
除非您有许多其他实体,否则为什么不只是DROP DATABASE而从头开始呢?
StuartLC 2010年

161
保留用户特权。
bcmcfc 2010年

5
我只是意识到,与此同时,您得到了Dion Truter的答案,该答案比我的答案更完整,建议改为接受。(“删除所有表格”部分不属于我的范围)
chiccodoro 2012年

5
仅供参考,如果您恰好安装了phpMyAdmin,则很容易选择所有表并将其删除。
用户

1
确实如此,但仅适用于4.x版中的phpMyAdmin。如果选择所有表并Drop从下拉菜单中选择,则可以取消选中该Foreign key check复选框。
jmarceli 2013年

Answers:


473

我发现生成的drop语句集很有用,并建议进行以下调整:

  1. 像这样将生成的drop限制到您的数据库中:
SELECT concat('DROP TABLE IF EXISTS `', table_name, '`;')
FROM information_schema.tables
WHERE table_schema = 'MyDatabaseName';

注意1:这不会执行DROP语句,只是提供了它们的列表。您将需要将输出剪切并粘贴到SQL引擎中以执行它们。

注意2:如果您有VIEW,则必须将每个DROP TABLE `VIEW_NAME`语句DROP VIEW `VIEW_NAME`手动更正。

  1. 请注意,根据http://dev.mysql.com/doc/refman/5.5/zh-CN/drop-table.html,使用层叠进行删除是没有意义的/具有误导性的:

“ RESTRICT和CASCADE允许简化移植。在MySQL 5.5中,它们什么也不做。”

因此,如果需要,为了使drop语句起作用:

SET FOREIGN_KEY_CHECKS = 0

这将禁用参照完整性检查-因此,完成所需的删除操作后,您将希望使用

SET FOREIGN_KEY_CHECKS = 1
  1. 最终执行应如下所示:
SET FOREIGN_KEY_CHECKS = 0;
-- Your semicolon separated list of DROP statements here
SET FOREIGN_KEY_CHECKS = 1;

注意:要使用SELECT的输出更容易,mysql -B选项可以提供帮助。


6
@Timmm:我在答案中写了3滴-但是,这也不会执行。您必须从Stackoverflow复制它们并将其粘贴到MySQL Workbench或任何地方。通过上面的选择,您可以“免费”获得所有匹配的液滴。您只需要复制粘贴即可。
chiccodoro 2012年

3
是的,我知道,但是我想在脚本中使用它。我最终实际要做的是DROP DATABASE foo; CREATE DATABASE foo;,虽然不尽相同,但对我有用。
Timmmm 2012年

2
有数百个表时不方便,但如果不能重新创建数据库,总比没有好。
Nicolas Raoul

2
@Timmmm:再看一遍-是的,它不能完全回答问题。Jean的答案很有希望-它既可以自动生成DROP语句并执行它们,同时可以在前后适当地应用SET FOREIGN_KEY_CHECKS。
chiccodoro 2014年

1
如果您使用的是Linux或Mac,请使用终端,它将可以登录到您的mysql帐户类型:mysql -u <用户名> -p,然后单击Enter,现在输入密码,选择数据库,然后编写上述代码删除表
ismnoiet

132

http://www.devdaily.com/blog/post/mysql/drop-mysql-tables-in-any-order-foreign-keys中

SET FOREIGN_KEY_CHECKS = 0;
drop table if exists customers;
drop table if exists orders;
drop table if exists order_details;
SET FOREIGN_KEY_CHECKS = 1;

(请注意,这个答案它如何禁用外键检查,以便能够删除以任意顺序表。没有回答如何自动生成所有现有表下拉表报表和在一个脚本执行它们。吉恩的答案确实。)


10
如果使用MySQL Workbench,则可以通过选择左列中的所有表,右键单击,然后单击“删除表”选项来避免键入所有表名。IT部门将生成SQL,您可以在SET FOREGIN_KEY_CHECKS语句之间复制和粘贴该SQL-在其他GUI中也可能类似。
克里斯,2012年

感谢帮助,@chris超级帮助,应该添加一个答案
安德鲁

97

这是修改SurlyDre的存储过程,以便忽略外键:

DROP PROCEDURE IF EXISTS `drop_all_tables`;

DELIMITER $$
CREATE PROCEDURE `drop_all_tables`()
BEGIN
    DECLARE _done INT DEFAULT FALSE;
    DECLARE _tableName VARCHAR(255);
    DECLARE _cursor CURSOR FOR
        SELECT table_name 
        FROM information_schema.TABLES
        WHERE table_schema = SCHEMA();
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET _done = TRUE;

    SET FOREIGN_KEY_CHECKS = 0;

    OPEN _cursor;

    REPEAT FETCH _cursor INTO _tableName;

    IF NOT _done THEN
        SET @stmt_sql = CONCAT('DROP TABLE ', _tableName);
        PREPARE stmt1 FROM @stmt_sql;
        EXECUTE stmt1;
        DEALLOCATE PREPARE stmt1;
    END IF;

    UNTIL _done END REPEAT;

    CLOSE _cursor;
    SET FOREIGN_KEY_CHECKS = 1;
END$$

DELIMITER ;

call drop_all_tables(); 

DROP PROCEDURE IF EXISTS `drop_all_tables`;

2
在表上工作,无法删除视图。仍然大大减少了我的打字:) thx。
chrisinmtown

7年后,我会说你应该_tableName用反引号引起来。否则,它将在某些表(例如group或其他关键字)上失败。
sashaaero

注意意见!从information_schema.TABLES中选择table_name。table_schema = SCHEMA()AND table_type =“ BASE TABLE”;
劳伦特·贝洛伊

42

上面的每种方法都比该AFAICT包含更多的工作...

( mysqldump --add-drop-table --no-data -u root -p database | grep 'DROP TABLE' ) > ./drop_all_tables.sql
mysql -u root -p database < ./drop_all_tables.sql

2
为什么不只是通过管道mysqldump传送到mysql,而无需通过文件?
罗尔夫

2
@Rolf没有特别的原因。把自己打昏。
SkyLeach

2
谢谢,我已经做了,删除括号并mysqldump插入grepmysql,它可以正常工作。再次感谢您的解决方案,很好。
罗尔夫(Rolf)'18年

5
这是缺少外键约束的;我已根据您的回答在此处添加了bash脚本:gist.github.com/cweinberger/c3f2882f42db8bef9e605f094392468f
cweinberger

太聪明了!
zx1986

25

这个答案

执行:

  use `dbName`; --your db name here
  SET FOREIGN_KEY_CHECKS = 0; 
  SET @tables = NULL;
  SET GROUP_CONCAT_MAX_LEN=32768;

  SELECT GROUP_CONCAT('`', table_schema, '`.`', table_name, '`') INTO @tables
  FROM   information_schema.tables 
  WHERE  table_schema = (SELECT DATABASE());
  SELECT IFNULL(@tables, '') INTO @tables;

  SET        @tables = CONCAT('DROP TABLE IF EXISTS ', @tables);
  PREPARE    stmt FROM @tables;
  EXECUTE    stmt;
  DEALLOCATE PREPARE stmt;
  SET        FOREIGN_KEY_CHECKS = 1;

这将从当前使用的数据库中删除表。您可以使用设置当前数据库use


否则,Dion接受的答案会更简单,除非您需要执行两次,第一次是获取查询,第二次是执行查询。我提供了一些愚蠢的反引号,以避开数据库和表名中的特殊字符。

  SELECT CONCAT('DROP TABLE IF EXISTS `', table_schema, '`.`', table_name, '`;')
  FROM   information_schema.tables
  WHERE  table_schema = 'dbName'; --your db name here

短而干净的解决方案。比程序替代方法更好。
拉斐尔·雷南·帕切科

16

这是一个基于游标的解决方案。有点长,但可以作为单个SQL批处理:

DROP PROCEDURE IF EXISTS `drop_all_tables`;

DELIMITER $$
CREATE PROCEDURE `drop_all_tables`()
BEGIN
    DECLARE _done INT DEFAULT FALSE;
    DECLARE _tableName VARCHAR(255);
    DECLARE _cursor CURSOR FOR
        SELECT table_name 
        FROM information_schema.TABLES
        WHERE table_schema = SCHEMA();
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET _done = TRUE;

    OPEN _cursor;

    REPEAT FETCH _cursor INTO _tableName;

    IF NOT _done THEN
        SET @stmt_sql = CONCAT('DROP TABLE ', _tableName);
        PREPARE stmt1 FROM @stmt_sql;
        EXECUTE stmt1;
        DEALLOCATE PREPARE stmt1;
    END IF;

    UNTIL _done END REPEAT;

    CLOSE _cursor;

END$$

DELIMITER ;

call drop_all_tables(); 

DROP PROCEDURE IF EXISTS `drop_all_tables`;

2
很好,但是不幸的是它不能处理外键。
Timmmm 2012年

11

你可以做:

select concat('drop table if exists ', table_name, ' cascade;')
  from information_schema.tables;

然后运行生成的查询。他们将删除当前数据库中的每个表。

是一些drop table命令帮助。


上面的答案假定将||其设置为串联运算符。更具体地说,MySQL SQL模式包含PIPES_AS_CONCAT。参考:dev.mysql.com/doc/refman/5.0/en/...
约努茨G.斯坦

@Ionut:太酷了!感谢您指出了这一点。修复了代码示例以concat代替||
Pablo Santa Cruz于2010年

9

我根据Dion Truter的答案提出了此修改,以使许多表变得更容易:

SET GROUP_CONCAT_MAX_LEN = 10000000;
SELECT CONCAT('SET FOREIGN_KEY_CHECKS=0;\n', 
              GROUP_CONCAT(CONCAT('DROP TABLE IF EXISTS `', table_name, '`')
                           SEPARATOR ';\n'),
              ';\nSET FOREIGN_KEY_CHECKS=1;')
FROM information_schema.tables
WHERE table_schema = 'SchemaName';

这将整个内容返回到一个字段中,因此您可以复制一次并删除所有表(Copy Field Content (unquoted)在Workbench中使用)。如果您有很多桌子,您可能会在上遇到一些限制GROUP_CONCAT()。如果是这样,请增加max len变量(和max_allowed_packet,如有必要)。


SET GROUP_CONCAT_MAX_LEN是我需要的技巧。我有一个正在运行的脚本,但是第一次总是会失败,并且表名被截断,然后在第二次运行时成功完成。谢谢!
dualmon

8

总是在话题上搜寻,总是让我想到这样的问题,因此,这里正在工作的mysql代码删除了两个表和视图:

DROP PROCEDURE IF EXISTS `drop_all_tables`;

DELIMITER $$
CREATE PROCEDURE `drop_all_tables`()
BEGIN
    DECLARE _done INT DEFAULT FALSE;
    DECLARE _tableName VARCHAR(255);
    DECLARE _cursor CURSOR FOR
        SELECT table_name
        FROM information_schema.TABLES
        WHERE table_schema = SCHEMA();
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET _done = TRUE;

    SET FOREIGN_KEY_CHECKS = 0;

    OPEN _cursor;

    REPEAT FETCH _cursor INTO _tableName;

    IF NOT _done THEN
        SET @stmt_sql1 = CONCAT('DROP TABLE IF EXISTS ', _tableName);
        SET @stmt_sql2 = CONCAT('DROP VIEW IF EXISTS ', _tableName);

        PREPARE stmt1 FROM @stmt_sql1;
        PREPARE stmt2 FROM @stmt_sql2;

        EXECUTE stmt1;
        EXECUTE stmt2;

        DEALLOCATE PREPARE stmt1;
        DEALLOCATE PREPARE stmt2;
    END IF;

    UNTIL _done END REPEAT;

    CLOSE _cursor;
    SET FOREIGN_KEY_CHECKS = 1;
END$$

DELIMITER ;

call drop_all_tables();

DROP PROCEDURE IF EXISTS `drop_all_tables`;

7

一个衬里从给定数据库中删除所有表:

echo "DATABASE_NAME"| xargs -I{} sh -c "mysql -Nse 'show tables' {}| xargs -I[] mysql -e 'SET FOREIGN_KEY_CHECKS=0; drop table []' {}"

运行此命令将从数据库DATABASE_NAME中删除所有表。

与此有关的一件好事是,数据库名称仅被明确地写入一次。


1
这对我有用,但是,我不得不在macOS High Sierra上用-I替换-i
Ali Selcuk,

1
谢谢@AliSelcuk。-i和-I都可以在Ubuntu上使用,因此我将其更改为-I以便也可以在macOS上使用。
mgershen

1
非常有用,谢谢!我必须将-pPASSWORD密码(-p和PASSWORD之间没有空格)传递给两个mysql命令
Mike

6

这是通过bash脚本自动执行此操作的方法:

host=$1
dbName=$2
user=$3
password=$4

if [ -z "$1" ]
then
    host="localhost"
fi

# drop all the tables in the database
for i in `mysql -h$host -u$user -p$password $dbName -e "show tables" | grep -v Tables_in` ; do  echo $i && mysql -h$host -u$user -p$password $dbName -e "SET FOREIGN_KEY_CHECKS = 0; drop table $i ; SET FOREIGN_KEY_CHECKS = 1" ; done

真的很喜欢这种解决方案,但我看不到如何使用主机变量。它似乎未在for循环中的任何mysql调用中使用。
马修·扎克斯基斯基

1
抱歉,错过了将其放入命令中,对其进行了更新。
kfox

5

如果在linux(或任何其他支持管道,echo和grep的系统)中,则可以用以下一行代码完成:

echo "SET FOREIGN_KEY_CHECKS = 0;" > temp.txt; \
mysqldump -u[USER] -p[PASSWORD] --add-drop-table --no-data [DATABASE] | grep ^DROP >> temp.txt; \
echo "SET FOREIGN_KEY_CHECKS = 1;" >> temp.txt; \
mysql -u[USER] -p[PASSWORD] [DATABASE] < temp.txt;

我知道这是一个老问题,但是我认为这种方法既快速又简单。


2

在php中,其操作非常简单:

$pdo = new PDO('mysql:dbname=YOURDB', 'root', 'root');

$pdo->exec('SET FOREIGN_KEY_CHECKS = 0');

$query = "SELECT concat('DROP TABLE IF EXISTS ', table_name, ';')
          FROM information_schema.tables
          WHERE table_schema = 'YOURDB'";

foreach($pdo->query($query) as $row) {
    $pdo->exec($row[0]);
}

$pdo->exec('SET FOREIGN_KEY_CHECKS = 1');

只需记住将YOURDB更改为数据库的名称,并且显然将用户/密码更改为即可。


2

在像bash / zsh这样的Linux shell中:

DATABASE_TO_EMPTY="your_db_name";
{ echo "SET FOREIGN_KEY_CHECKS = 0;" ; \
  mysql "$DATABASE_TO_EMPTY" --skip-column-names -e \
  "SELECT concat('DROP TABLE IF EXISTS ', table_name, ';') \
   FROM information_schema.tables WHERE table_schema = '$DATABASE_TO_EMPTY';";\
  } | mysql "$DATABASE_TO_EMPTY"

这将生成命令,然后立即将它们通过管道传递到第二个客户端实例,该实例将删除表。

当然,聪明的地方是从其他答案中复制的-我只是想复制并粘贴单线(ish)来实际完成 OP想要的工作。

注意,当然,除非安全性设置很低,否则还必须将凭据(两次)放入这些mysql命令中。(或者,您可以为您的mysql命令加上别名以包含您的信誉。)



2

使用命令行中的一行删除数据库中的所有表:

mysqldump -u [user_name] -p[password] -h [host_name] --add-drop-table --no-data [database_name] | grep ^DROP | mysql -u [user_name] -p[password] -h [host_name] [database_name]

其中[user_name],[password],[host_name]和[database_name]必须替换为真实数据(用户,密码,主机名,数据库名)。


1

这是一个很旧的帖子,但是我认为这里的答案都没有真正回答这个问题,所以希望我的帖子对人们有所帮助!

我在另一个非常适合我的问题上找到了该解决方案:

mysql -Nse 'show tables' DB_NAME | while read table; do mysql -e "SET FOREIGN_KEY_CHECKS=0; truncate table \`$table\`" DB_NAME; done

实际上,这将清空数据库中的所有表DB_NAME,而不仅显示TRUNCATE命令行。

希望这可以帮助!


有用,但并不能真正回答问题。
jrosell '09

1

在@Dion Truter和@Wade Williams的答案的基础上,下面的shell脚本在首先显示它要运行的内容之后,将删除所有表,并为您提供使用Ctrl-C中止的机会。

#!/bin/bash

DB_HOST=xxx
DB_USERNAME=xxx
DB_PASSWORD=xxx
DB_NAME=xxx

CMD="mysql -sN -h ${DB_HOST} -u ${DB_USERNAME} -p${DB_PASSWORD} ${DB_NAME}"

# Generate the drop statements
TMPFILE=/tmp/drop-${RANDOM}.sql
echo 'SET FOREIGN_KEY_CHECKS = 0;' > ${TMPFILE}
${CMD} $@ >> ${TMPFILE} << ENDD
    SELECT concat('DROP TABLE IF EXISTS \`', table_name, '\`;')
    FROM information_schema.tables
    WHERE table_schema = '${DB_NAME}';
ENDD
echo 'SET FOREIGN_KEY_CHECKS = 1;' >> ${TMPFILE}

# Warn what we are about to do
echo
cat ${TMPFILE}
echo
echo "Press ENTER to proceed (or Ctrl-C to abort)."
read

# Run the SQL
echo "Dropping tables..."
${CMD} $@ < ${TMPFILE}
echo "Exit status is ${?}."
rm ${TMPFILE}

0

此解决方案基于@SkyLeach答案,但支持使用外键删除表。

echo "SET FOREIGN_KEY_CHECKS = 0;" > ./drop_all_tables.sql
mysqldump --add-drop-table --no-data -u user -p dbname | grep 'DROP TABLE' >> ./drop_all_tables.sql
echo "SET FOREIGN_KEY_CHECKS = 1;" >> ./drop_all_tables.sql
mysql -u user -p dbname < ./drop_all_tables.sql


0

简单明了(可能是)。

可能不是一个很好的解决方案,但这对我有用,并节省了我的时间。

适用于服务器版本:5.6.38 MySQL社区服务器(GPL)

我遵循的步骤:

 1. generate drop query using concat and group_concat.
 2. use database
 3. disable key constraint check
 4. copy the query generated from step 1
 5. enable key constraint check
 6. run show table

MySQL外壳

mysql> SYSTEM CLEAR;
mysql> SELECT CONCAT('DROP TABLE IF EXISTS `', GROUP_CONCAT(table_name SEPARATOR '`, `'), '`;') AS dropquery FROM information_schema.tables WHERE table_schema = 'emall_duplicate';
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| dropquery                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| DROP TABLE IF EXISTS `admin`, `app`, `app_meta_settings`, `commission`, `commission_history`, `coupon`, `email_templates`, `infopages`, `invoice`, `m_pc_xref`, `member`, `merchant`, `message_templates`, `mnotification`, `mshipping_address`, `notification`, `order`, `orderdetail`, `pattributes`, `pbrand`, `pcategory`, `permissions`, `pfeatures`, `pimage`, `preport`, `product`, `product_review`, `pspecification`, `ptechnical_specification`, `pwishlist`, `role_perms`, `roles`, `settings`, `test`, `testanother`, `user_perms`, `user_roles`, `users`, `wishlist`; |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> USE emall_duplicate;
Database changed
mysql> SET FOREIGN_KEY_CHECKS = 0;                                                                                                                                                   Query OK, 0 rows affected (0.00 sec)

// copy and paste generated query from step 1
mysql> DROP TABLE IF EXISTS `admin`, `app`, `app_meta_settings`, `commission`, `commission_history`, `coupon`, `email_templates`, `infopages`, `invoice`, `m_pc_xref`, `member`, `merchant`, `message_templates`, `mnotification`, `mshipping_address`, `notification`, `order`, `orderdetail`, `pattributes`, `pbrand`, `pcategory`, `permissions`, `pfeatures`, `pimage`, `preport`, `product`, `product_review`, `pspecification`, `ptechnical_specification`, `pwishlist`, `role_perms`, `roles`, `settings`, `test`, `testanother`, `user_perms`, `user_roles`, `users`, `wishlist`;
Query OK, 0 rows affected (0.18 sec)

mysql> SET FOREIGN_KEY_CHECKS = 1;
Query OK, 0 rows affected (0.00 sec)

mysql> SHOW tables;
Empty set (0.01 sec)

mysql> 

在此处输入图片说明


-1

我将以下内容用于MSSQL服务器:

if (DB_NAME() = 'YOUR_DATABASE') 
begin
    while(exists(select 1 from INFORMATION_SCHEMA.TABLE_CONSTRAINTS where CONSTRAINT_TYPE='FOREIGN KEY'))
    begin
         declare @sql nvarchar(2000)
         SELECT TOP 1 @sql=('ALTER TABLE ' + TABLE_SCHEMA + '.[' + TABLE_NAME + '] DROP CONSTRAINT [' + CONSTRAINT_NAME + ']')
         FROM information_schema.table_constraints
         WHERE CONSTRAINT_TYPE = 'FOREIGN KEY'
         exec (@sql)
         PRINT @sql
    end

    while(exists(select 1 from INFORMATION_SCHEMA.TABLES))
    begin
         declare @sql2 nvarchar(2000)
         SELECT TOP 1 @sql2=('DROP TABLE ' + TABLE_SCHEMA + '.[' + TABLE_NAME + ']')
         FROM INFORMATION_SCHEMA.TABLES
        exec (@sql2)
        PRINT @sql2
    end
end
else
    print('Only run this script on the development server!!!!')

用数据库名称替换YOUR_DATABASE或删除整个IF语句(我喜欢增加的安全性)。


-7

最佳解决方案到目前为止对我来说

选择数据库->右键单击->任务->生成脚本 -将打开用于生成脚本的向导。在“设置脚本”选项中选择对象后,单击“ 高级按钮”。在“脚本删除并创建”选择脚本DROP

运行脚本。


几乎可以用了,但是我单击了绿色按钮,然后单击了蓝色按钮,然后在左边有了一个方框,然后单击“取消”,但是我喝了咖啡却忘了它。
罗尔夫(Rolf)

您甚至可以解释点击的位置吗?有涉及的工具吗?
Nico Haase
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.