MySQL DROP все таблицы, игнорируя внешние ключи - PullRequest
338 голосов
/ 13 августа 2010

Есть ли хороший простой способ удалить все таблицы из базы данных MySQL, игнорируя любые ограничения внешнего ключа, которые могут там быть?

Ответы [ 22 ]

387 голосов
/ 23 ноября 2011

Я нашел сгенерированный набор операторов отбрасывания полезным и рекомендую следующие настройки:

  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они ничего не делают. "

Поэтому, чтобы операторы drop работали, если вам нужно:

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.

124 голосов
/ 13 августа 2010

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

(Обратите внимание, что это ответ о том, как отключить проверку внешнего ключа, чтобы иметь возможность отбрасывать таблицы в произвольном порядке. Он не отвечает, как автоматически генерировать операторы отбрасываемых таблиц для всех существующих таблиц и выполнять их в одном скрипте . Жан ответ делает.)

87 голосов
/ 16 октября 2012

Вот хранимая процедура 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`;
32 голосов
/ 15 января 2016

каждый вышеприведенный подход включает в себя гораздо больше работы, чем этот 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
18 голосов
/ 13 февраля 2014

С этот ответ ,

выполнить:

  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 голосов
/ 15 апреля 2012

Вот решение на основе курсора. Вроде долго, но работает как один пакет 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`;
11 голосов
/ 13 августа 2010

Вы можете сделать:

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

Затем запустите сгенерированные запросы. Они будут отбрасывать каждую таблицу в текущей базе данных.

Здесь - некоторая справка по команде drop table.

9 голосов
/ 24 июля 2013

Я придумал эту модификацию в ответе Дион Трутера, чтобы упростить многие таблицы:

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, если необходимо).

6 голосов
/ 07 августа 2016

Один вкладыш для удаления всех таблиц из заданной базы данных:

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

Запуск этой команды приведет к удалению всех таблиц из базы данных DATABASE_NAME.

И приятно то, что база данныхимя пишется явно только один раз.

5 голосов
/ 10 апреля 2013

Вот автоматический способ сделать это с помощью 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
...