MySQL DROP все таблицы, игнорируя внешние ключи

232

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

  • 1
    Если у вас нет множества других объектов, почему бы просто не DROP DATABASE и начать с нуля?
  • 137
    Для сохранения привилегий пользователя.
Показать ещё 6 комментариев
Теги:
foreign-keys
innodb
sql-drop

17 ответов

251
Лучший ответ

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

  • Ограничьте сгенерированные капли в своей базе данных следующим образом:
SELECT concat('DROP TABLE IF EXISTS ', table_name, ';')
FROM information_schema.tables
WHERE table_schema = 'MyDatabaseName';
  1. Примечание, за http://dev.mysql.com/doc/refman/5.5/en/drop-table.html падение с помощью каскада бессмысленно/вводит в заблуждение:

"RESTRICT и CASCADE разрешено упростить перенос. В MySQL 5.5 они ничего не делают".

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

SET FOREIGN_KEY_CHECKS = 0

Это приведет к отключению проверки ссылочной целостности - поэтому, когда вы закончите выполнение необходимых капель, вам понадобится reset проверка ключа с помощью

SET FOREIGN_KEY_CHECKS = 1
  • 60
    Это дает мне запросы, но на самом деле не выполняет их ...
  • 6
    @Timmm: я написал 3 капли в своем ответе - однако, это не выполняет их также. Вы должны скопировать их из Stackoverflow и вставить их в MySQL Workbench или где угодно. С помощью выбора выше вы получаете все соответствующие капли "бесплатно". Вы просто должны скопировать и вставить их.
Показать ещё 9 комментариев
105

Из 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;

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

  • 9
    Если вы используете MySQL Workbench, вы можете избежать ввода всех имен таблиц, выбрав все таблицы в левом столбце, щелкнув правой кнопкой мыши и выбрав опцию «удалить таблицы». Он сгенерирует SQL, который вы можете скопировать и вставить между инструкциями SET FOREGIN_KEY_CHECKS - вероятно, аналогично в других графических интерфейсах.
  • 0
    Спасибо, полезно, и @ Крис супер полезно, должен добавить ответ
63

Здесь хранится хранимая процедура 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
    Работает на таблицах, не удаляет представления. Все еще уменьшил мой набор текста :) спасибо.
12

От этого ответа,

выполнить:

  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 принятый ответ проще, за исключением того, что вам нужно выполнить его дважды, сначала для получения запроса, а второй для выполнения запроса. Я предоставил несколько глупых back-ticks, чтобы избежать специальных символов в именах db и таблиц.

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

Здесь находится решение на основе курсора. Kinda longy, но работает как единый пакет 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
    Хорошо, но, к сожалению, он не обрабатывает внешние ключи.
8

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

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

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

Здесь есть помощь по команде drop table.

  • 0
    Приведенный выше ответ предполагает, что || устанавливается как оператор конкатенации. В частности, режим SQL MySQL содержит PIPES_AS_CONCAT . Ссылка: dev.mysql.com/doc/refman/5.0/en/…
  • 0
    @Ionut: круто! Спасибо что подметил это. Исправлен пример кода для использования concat вместо ||
7

Я придумал эту модификацию для ответа 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(). Если это так, увеличьте максимальную переменную len (и max_allowed_packet, если необходимо).

  • 0
    SET GROUP_CONCAT_MAX_LEN был трюк, который мне был нужен. У меня был скрипт, который работал, но всегда не удавалось в первый раз с каким-либо усеченным именем таблицы, а затем успешно завершался при запуске во второй раз. Спасибо!
4

каждый вышеприведенный подход включает намного больше работы, чем этот 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
    Лучший ответ здесь, чувак.
  • 1
    почему бы просто не mysqldump в mysql , не пройдя через файл?
Показать ещё 5 комментариев
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;

Я знаю, что это старый вопрос, но я думаю, что этот метод быстрый и простой.

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 на имя вашей базы данных и, очевидно, пользователь/пароль.

3

Вот автоматический способ сделать это с помощью bash script:

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
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 включить ваши кредиты.)

0

Основываясь на ответе @Dion Truter и @Wade Williams, следующая оболочка script будет удалять все таблицы, сначала показывая, что она собирается запускать, и дает вам возможность прервать использование 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

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

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 High Sierra
  • 1
    Спасибо @AliSelcuk. И -i, и -I у меня работают в Ubuntu, поэтому я изменю его на -I, чтобы это работало и для macOS.
Показать ещё 1 комментарий
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
    Полезно, но на самом деле это не отвечает на вопрос.
-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 (мне нравится добавленная безопасность).

-2

Лучшее решение для меня до сих пор

Выберите База данных → Щелкните правой кнопкой мыши → Задачи → Сгенерировать скрипты - откроет мастер для генерации скриптов. После выбора объектов в параметре Set Scripting нажмите Расширенная кнопка. В разделе "Script DROP и CREATE" выберите Script DROP.

Запустите script.

  • 0
    Это почти сработало, но я щелкнул зеленую кнопку перед синей кнопкой, получил коробку слева и нажал «Отмена», но потом я выпил свой кофе и забыл об этом.
  • 0
    Не могли бы вы объяснить, где вы нажали? Есть ли какой-нибудь инструмент для этого?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню