2010-08-13 115 views
253

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

+1

除非你有很多其他实体的,为什么不删除数据库和白手起家? – StuartLC 2010-08-13 12:31:48

+119

保存用户授权。 – bcmcfc 2010-08-17 14:09:44

+4

我刚刚意识到,与此同时,你得到了一个比我更完整的Dion Truter的答案,并建议接受它。 (“drop * all * tables”部分不在我的范围内) – chiccodoro 2012-05-03 07:24:07

回答

281

我发现生成的一组有用下降报表,并建议这些调整:

  1. 限制所产生的水滴到你的数据库是这样的:
SELECT concat('DROP TABLE IF EXISTS ', table_name, ';') 
FROM information_schema.tables 
WHERE table_schema = 'MyDatabaseName'; 

注:这确实不执行DROP语句,它只是给你一个列表。你将需要剪切和粘贴输出到你的SQL引擎来执行它们。

  • 注意,每http://dev.mysql.com/doc/refman/5.5/en/drop-table.html,与级联滴是无意义/误导:
  • “RESTRICT和CASCADE被允许使移植更容易在MySQL 5.5,他们什么都不做。“

    因此,为了使降报表工作,如果你需要:

    SET FOREIGN_KEY_CHECKS = 0 
    

    这将禁用参照完整性检查 - 所以你做执行,你需要滴的时候,你会想重置密钥检查与

    SET FOREIGN_KEY_CHECKS = 1 
    
  • 最终执行应该是这样的:
  • SET FOREIGN_KEY_CHECKS = 0; 
    -- Your semicolon separated list of DROP statements here 
    SET FOREIGN_KEY_CHECKS = 1; 
    

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

    +52

    这给了我查询,但并没有真正执行它们...... – Timmmm 2012-10-08 12:52:22

    +5

    @Timmm:我在答案中写了3滴 - 但是,这不会执行他们要么。你必须从Stackoverflow复制它们并将它们粘贴到你的MySQL Workbench或者任何其他的。使用上面的选择,您可以免费获得所有匹配的滴剂。你只需要复制粘贴它们。 – chiccodoro 2012-11-15 09:24:42

    +2

    是的,我知道,但我想在脚本中使用它。我最终做的是'DROP DATABASE foo; CREATE DATABASE foo;',这是不一样的,但为我工作。 – Timmmm 2012-11-15 09:44:38

    113

    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; 
    

    (注意,这个回答如何为了能够放弃以任意顺序表禁用外键检查它没有回答如何自动生成下拉表的语句所有现有表和一个脚本执行它们琼的回答没有)

    +9

    如果使用MySQL Workbench,则可以避免必须通过选择所有表来键入所有表名在左列中,右键单击,然后选择“删除表格”选项。 IT将生成SQL,您可以在SET FOREGIN_KEY_CHECKS语句之间复制和粘贴 - 也可能与其他GUI类似。 – chris 2012-04-27 18:47:01

    +0

    感谢帮助,@chris超级有用,应该加个答案 – Andrew 2017-12-07 16:52:38

    8

    你可以这样做:。

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

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

    Heredrop table命令的一些帮助。

    +0

    上面的答案假设'||'被设置为连接运算符。更具体地说,MySQL SQL模式包含'PIPES_AS_CONCAT'。参考:http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html#sqlmode_pipes_as_concat – 2010-08-13 12:37:52

    +0

    @Ionut:cool!感谢您指出了这一点。修正了使用'concat'代替'||'的代码示例 – 2010-08-13 12:40:49

    13

    这是基于光标的解决方案。有点冗长,但可以作为一个单独的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-10-08 12:53:15

    67

    下面是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`; 
    
    +1

    对表格无效,无法删除视图。仍然减少我的打字大量:) THX。 – chrisinmtown 2016-08-03 16:32:41

    4

    这里是一个自动化的方式通过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 
    
    7

    我想出了在翁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'; 
    

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

    +0

    SET GROUP_CONCAT_MAX_LEN是我需要的技巧。我有一个正在工作的脚本,但第一次使用一些截断的表名时总是失败,然后在第二次运行时成功完成。谢谢! – dualmon 2014-05-07 00:44:27

    3

    在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更改为您的数据库的名称,显然用户名/密码。

    13

    this answer

    执行:

    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 
    
    1

    在Linux壳诸如bash/zsh中:

    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命令,包括你的creds。)

    4

    如果在linux(或支持的管道,回声和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; 
    

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

    -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语句(我喜欢的增加安全性)。

    0

    这是一个很老的帖子,但这里没有一个答案真的回答了我的观点,所以我希望我的帖子能够帮助人们!

    我发现了另一个问题这个解决方案可以很好地表现了我:

    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命令行。

    希望这会有所帮助!

    +0

    有用但它并不真正回答这个问题。 – jrosell 2016-09-21 12:12:07

    8

    上述每种方法包括比这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 
    
    +0

    这里最好的答案,男人。 – 2018-02-19 09:22:26

    -3

    最好的解决方案我至今

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

    运行脚本。

    2

    一个一个班轮下降从一个给定的数据库中的所有表:

    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

    这工作对我来说,但是,我不得不用-i替换-i在macOS高Sierra – 2018-01-01 11:53:19

    +1

    谢谢@AliSelcuk。 -i和-I在Ubuntu上适用于我,所以我会将其更改为-I,以便此操作也适用于macOS。 – mgershen 2018-01-01 12:23:36

    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} [email protected] >> ${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} [email protected] < ${TMPFILE} 
    echo "Exit status is ${?}." 
    rm ${TMPFILE} 
    
    0

    谷歌搜索的话题总是把我带到这太问题所以在这里工作是删除表和视图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`;