MySQL DROP所有表,忽略外键

bcm*_*cfc 358 mysql innodb foreign-keys sql-drop

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

Dio*_*ter 411

我发现生成的drop语句集很有用,并建议这些调整:

  1. 将生成的drop限制为数据库,如下所示:
SELECT concat('DROP TABLE IF EXISTS `', table_name, '`;')
FROM information_schema.tables
WHERE table_schema = 'MyDatabaseName';
Run Code Online (Sandbox Code Playgroud)

注意:这不执行DROP语句,它只是给你一个列表.您需要将输出剪切并粘贴到SQL引擎中以执行它们.

  1. 请注意,根据http://dev.mysql.com/doc/refman/5.5/en/drop-table.html,使用cascade删除是没有意义/误导性的:

"允许RESTRICT和CASCADE使移植更容易.在MySQL 5.5中,它们什么都不做."

因此,如果您需要,可以使drop语句正常工作:

SET FOREIGN_KEY_CHECKS = 0
Run Code Online (Sandbox Code Playgroud)

这将禁用参照完整性检查 - 因此当您完成所需的丢弃后,您将需要重置密钥检查

SET FOREIGN_KEY_CHECKS = 1
Run Code Online (Sandbox Code Playgroud)
  1. 最终执行应如下所示:
SET FOREIGN_KEY_CHECKS = 0;
-- Your semicolon separated list of DROP statements here
SET FOREIGN_KEY_CHECKS = 1;
Run Code Online (Sandbox Code Playgroud)

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

  • @Timmm:我的答案中写了3滴 - 然而,这也没有执行.您必须从Stackoverflow复制它们并将它们粘贴到您的MySQL Workbench或其中.通过上面的选择,您可以"免费"获得所有匹配的滴.你只需要复制粘贴它们. (6认同)
  • 是的,我知道,但我想在脚本中使用它.我最终实际做的是`DROP DATABASE foo; CREATE DATABASE foo;`,这对我来说并不完全相同. (3认同)
  • @Timmmm:再看一遍——你是对的,它并没有完全回答这个问题。Jean 的回答看起来很有希望——它会自动生成 DROP 语句并执行它们,同时在前后正确应用 SET FOREIGN_KEY_CHECKS。 (3认同)
  • 当有数百个表时不方便,但如果不能重新创建数据库则优于空. (2认同)

chi*_*oro 128

来自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;
Run Code Online (Sandbox Code Playgroud)

(请注意,这解释了如何禁用外键检查以便能够以任意顺序删除表.它没有回答如何为所有现有表自动生成drop-table语句并在单个脚本中执行它们.Jean的回答确实.)

  • 如果使用MySQL Workbench,则可以通过选择左列中的所有表,右键单击,然后选择"drop tables"选项来避免键入所有表名.IT将生成可以在SET FOREGIN_KEY_CHECKS语句之间复制和粘贴的SQL - 在其他GUI中也可能类似. (10认同)

Jea*_*amp 89

这里修改了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`;
Run Code Online (Sandbox Code Playgroud)

  • 适用于表,无法删除视图.仍然减少了我的打字大量:) thx. (2认同)

Sky*_*ach 39

上述每种方法都包含了比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
Run Code Online (Sandbox Code Playgroud)

  • 这个缺少外键约束; 我根据你的答案在这里添加了一个bash脚本:https://gist.github.com/cweinberger/c3f2882f42db8bef9e605f094392468f (4认同)
  • 为什么不直接通过管道将 `mysqldump` 传送到 `mysql`,而不通过文件? (2认同)
  • @Rolf没有特别的理由.把自己打昏. (2认同)
  • 谢谢,我已经做了,删除括号并将管道`mysqldump`导入`grep`到`mysql`,它可以工作.再次感谢您的解决方案,这很好. (2认同)

naw*_*fal 24

这个答案,

执行:

  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;
Run Code Online (Sandbox Code Playgroud)

这会从当前正在使用的数据库中删除表.您可以使用设置当前数据库use.


或者,除非您需要执行两次,首先获取查询,然后执行查询,否则Dion接受的答案更简单.我提供了一些愚蠢的反向标记来逃避数据库和表名中的特殊字符.

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

  • 简短而干净的解决方案。比替代程序要好得多。 (2认同)

Sur*_*Dre 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`;
Run Code Online (Sandbox Code Playgroud)

  • 很好,但不幸的是它不处理外键. (2认同)

Pab*_*ruz 11

你可以做:

select concat('drop table if exists ', table_name, ' cascade;')
  from information_schema.tables;
Run Code Online (Sandbox Code Playgroud)

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

drop table命令的一些帮助.


Rya*_*n P 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';
Run Code Online (Sandbox Code Playgroud)

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


mge*_*hen 7

从给定数据库中删除所有表的一个内容:

echo "DATABASE_NAME"| xargs -I{} sh -c "mysql -Nse 'show tables' {}| xargs -I[] mysql -e 'SET FOREIGN_KEY_CHECKS=0; drop table []' {}"
Run Code Online (Sandbox Code Playgroud)

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

关于这一点的一个好处是数据库名称只显式写入一次.


Jso*_*owa 7

不使用过程从 SQL Select 查询复制返回值的一步解决方案。

SET FOREIGN_KEY_CHECKS = 0;
SET SESSION group_concat_max_len = 1000000;

SET @TABLES = NULL;
SELECT GROUP_CONCAT('`', table_schema, '`.`', table_name,'`') INTO @TABLES FROM information_schema.tables 
  WHERE table_schema = 'databaseName';

SET @TABLES = CONCAT('DROP TABLE IF EXISTS ', @TABLES);

PREPARE stmt FROM @TABLES;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET SESSION group_concat_max_len = 1024;
SET FOREIGN_KEY_CHECKS = 1
Run Code Online (Sandbox Code Playgroud)


Ser*_*aev 6

总是在话题上搜寻,总是让我想到这个问题,因此,这里是有效的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`;
Run Code Online (Sandbox Code Playgroud)


Pet*_*kiy 6

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

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]
Run Code Online (Sandbox Code Playgroud)

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


kfo*_*fox 5

以下是通过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 -u$user -p$password $dbName -e "show tables" | grep -v Tables_in` ; do  echo $i && mysql -u$user -p$password $dbName -e "SET FOREIGN_KEY_CHECKS = 0; drop table $i ; SET FOREIGN_KEY_CHECKS = 1" ; done
Run Code Online (Sandbox Code Playgroud)


mor*_*bio 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;
Run Code Online (Sandbox Code Playgroud)

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


sh6*_*210 5

只是一个温柔的提醒,

如果可能并且没有其他问题,您可以删除数据库并重新创建它。

  • 删除数据库<数据库名称>
  • 创建数据库 <数据库名称>

  • ...除非您还丢失了所有已设置的用户(带密码)、过程和视图。 (4认同)