MySQL DROP所有表,忽略外键

时间:2010-08-13 12:28:39

标签: mysql foreign-keys innodb sql-drop

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

23 个答案:

答案 0 :(得分:381)

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

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

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

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

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

      因此,如果您需要,可以使用drop语句:

      SET FOREIGN_KEY_CHECKS = 0
      

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

      重置密钥检查
      SET FOREIGN_KEY_CHECKS = 1
      
      1. 最终执行应如下所示:
      2. SET FOREIGN_KEY_CHECKS = 0;
        -- Your semicolon separated list of DROP statements here
        SET FOREIGN_KEY_CHECKS = 1;
        
        注意:使用SELECT的输出更容易,mysql -B选项可以帮助。

答案 1 :(得分:124)

来自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;

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

答案 2 :(得分:85)

这里修改了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`;

答案 3 :(得分:31)

上述每种方法都包含了比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

答案 4 :(得分:19)

来自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

答案 5 :(得分: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`;

答案 6 :(得分:11)

你可以这样做:

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

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

Heredrop table命令的一些帮助。

答案 7 :(得分: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';

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

答案 8 :(得分: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

答案 9 :(得分: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;

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

答案 10 :(得分:5)

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

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

运行此操作将删除数据库DATABASE_NAME中的所有表。

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

答案 11 :(得分:3)

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

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]

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

答案 12 :(得分:2)

一站式解决方案,无需使用过程从SQL Select查询中复制返回值。

SET FOREIGN_KEY_CHECKS = 0

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 FOREIGN_KEY_CHECKS = 1

答案 13 :(得分:2)

只需在此处放置一些有用的comment made by Jonathan Watt即可删除所有表格

MYSQL="mysql -h HOST -u USERNAME -pPASSWORD DB_NAME"
$MYSQL -BNe "show tables" | awk '{print "set foreign_key_checks=0; drop table `" $1 "`;"}' | $MYSQL
unset MYSQL

它对我有帮助,我希望它会有用

答案 14 :(得分:2)

谷歌搜索主题总是让我想到这个问题所以这里是工作mysql代码,删除BOTH表和视图:

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`;

答案 15 :(得分: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命令别名来包含你的信用。)

答案 16 :(得分: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更改为数据库名称,显然是用户/传递。

答案 17 :(得分: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}

答案 18 :(得分: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命令行。

希望这有帮助!

答案 19 :(得分: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

答案 20 :(得分:0)

简单明了(也许是)。

可能不是一个很好的解决方案,但这对我有用,并挽救了我的生活。

适用于服务器版本:5.6.38 MySQL Community Server(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 shell

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> 

enter image description here

答案 21 :(得分:-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语句(我喜欢增加的安全性)。

答案 22 :(得分:-6)

到目前为止

最佳解决方案

选择数据库 - &gt;右键单击 - &gt;任务 - &gt;生成脚本 - 将打开向导以生成脚本。在“设置脚本”选项中选择对象后,单击高级按钮。在&#34;脚本DROP和CREATE&#34; 下选择脚本DROP

运行脚本。