web-dev-qa-db-fra.com

MySQL supprime toutes les tables en ignorant les clés étrangères

Existe-t-il un moyen simple et agréable de supprimer toutes les tables d'une base de données MySQL, en ignorant les éventuelles contraintes de clé étrangère?

344
bcmcfc

J'ai trouvé le jeu d'instructions drop généré utile, et recommande ces modifications:

  1. Limitez les baisses générées à votre base de données comme ceci:
SELECT concat('DROP TABLE IF EXISTS `', table_name, '`;')
FROM information_schema.tables
WHERE table_schema = 'MyDatabaseName';

Remarque: ceci n'exécute pas les instructions DROP, il vous en donne juste une liste. Vous devrez couper et coller le résultat dans votre moteur SQL. pour les exécuter.

  1. Notez, par http://dev.mysql.com/doc/refman/5.5/en/drop-table.html , le fait de déposer en cascade est sans intérêt/trompeur:

"RESTRICT et CASCADE sont autorisés à faciliter le portage. Dans MySQL 5.5, ils ne font rien."

Par conséquent, pour que les instructions de suppression fonctionnent si vous avez besoin de:

SET FOREIGN_KEY_CHECKS = 0

Ceci désactivera les vérifications d’intégrité référentielle. Ainsi, lorsque vous aurez terminé d’effectuer les abandons dont vous avez besoin, vous voudrez réinitialiser la vérification des clés avec

SET FOREIGN_KEY_CHECKS = 1
  1. L'exécution finale devrait ressembler à:
SET FOREIGN_KEY_CHECKS = 0;
-- Your semicolon separated list of DROP statements here
SET FOREIGN_KEY_CHECKS = 1;

NB: pour utiliser la sortie de SELECT plus facilement, l'option mysql -B peut aider.

393
Dion Truter

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

(Notez que cela indique comment désactiver les contrôles de clé étrangère afin de pouvoir supprimer les tables dans un ordre arbitraire. Il ne explique pas comment générer automatiquement des instructions de suppression pour toutes les tables existantes et les exécuter dans un seul script. La réponse de Jean fait.)

124
chiccodoro

Voici la procédure stockée de SurlyDre modifiée afin que les clés étrangères soient ignorées:

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

chaque approche ci-dessus implique beaucoup plus de travail que celui-ci 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
34
SkyLeach

De cette réponse ,

exécuter:

  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;

Cela supprime les tables de la base de données en cours d'utilisation. Vous pouvez définir la base de données actuelle en utilisant use.


Ou bien, la réponse acceptée par Dion est plus simple, sauf que vous devez l'exécuter deux fois, d'abord pour obtenir la requête et ensuite pour l'exécuter. J'ai fourni quelques repères stupides pour échapper aux caractères spéciaux des noms de table et de base de données.

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

Voici une solution à base de curseur. Un peu long mais fonctionne comme un seul lot 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`;
16
SurlyDre

Tu peux faire:

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

Ensuite, exécutez les requêtes générées. Ils abandonneront chaque table de la base de données actuelle.

Here aide sur la commande drop table.

11
Pablo Santa Cruz

Je suis venu avec cette modification sur la réponse de Dion Truter pour le rendre plus facile avec de nombreux tableaux:

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

Cela renvoie la totalité du contenu dans un seul champ. Vous pouvez donc copier une fois et supprimer toutes les tables (utilisez Copy Field Content (unquoted) dans Workbench). Si vous avez beaucoup de tables, vous pouvez atteindre certaines limites sur GROUP_CONCAT(). Si tel est le cas, augmentez la variable max len (et max_allowed_packet, si nécessaire).

9
Ryan P

Une ligne pour supprimer toutes les tables d'une base de données donnée:

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

Cette opération supprimera toutes les tables de la base de données DATABASE_NAME.

Et une bonne chose à ce sujet est que le nom de la base de données n’est écrit explicitement qu’une fois.

7
mgershen

Voici un moyen automatisé de le faire via un script 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
5
kfox

Si vous êtes sous Linux (ou tout autre système prenant en charge la tuyauterie, echo et grep), vous pouvez le faire avec une seule ligne:

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;

Je sais que c’est une vieille question, mais je pense que cette méthode est simple et rapide.

5
moretti.fabio

Googler sur le sujet m’amène toujours à cette SO question. Voici donc du code mysql en cours d’utilisation qui supprime les DEUX tables et vues:

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`;
4
Sergey Alaev

Dans un shell Linux comme 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"

Cela générera les commandes, puis les dirigera immédiatement vers une seconde instance client qui supprimera les tables.

La partie intelligente est bien sûr copiée des autres réponses ici - je voulais juste un one-liner (ish) copier-coller pour réellement faire le travail le PO voulait.

Note Bien sûr, vous devrez mettre vos informations d'identification dans (deux fois) dans ces commandes mysql, aussi, sauf si vous avez une configuration de sécurité très basse. (ou vous pouvez alias votre commande mysql pour inclure vos creds.)

2
artfulrobot

Il suffit de mettre ici quelques informations utiles commentaire de Jonathan Watt pour supprimer toutes les tables

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

Cela m'aide et j'espère que cela pourrait être utile

2
Pavel.Solovyenko

En php c'est aussi simple que:

$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');

Rappelez-vous simplement de changer YOURDB avec le nom de votre base de données et évidemment avec l’utilisateur/le mot de passe.

2
nsbucky

S'appuyant sur les réponses de @Dion Truter et de @Wade Williams, le script Shell suivant supprime toutes les tables, après avoir tout d'abord montré ce qu'il est sur le point d'exécuter, et vous avoir laissé une chance d'abandonner à l'aide de 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}
1
Philip Callender

Ceci est un joli post ancien, mais aucune des réponses ici n'a vraiment répondu à la question à mon avis, j'espère donc que mon post aidera les gens!

J'ai trouvé cette solution sur une autre question qui fonctionne vraiment bien pour moi:

mysql -Nse 'show tables' DB_NAME | while read table; do mysql -e "SET FOREIGN_KEY_CHECKS=0; truncate table \`$table\`" DB_NAME; done

Cela va vider toutes vos tables de la base de données DB_NAME, et non seulement afficher la ligne de commande TRUNCATE.

J'espère que cela t'aides!

1
mokk
DB="your database name" \
    && mysql $DB < "SET FOREIGN_KEY_CHECKS=0" \
    && mysqldump --add-drop-table --no-data $DB | grep 'DROP TABLE' | grep -Ev "^$" | mysql $DB \
    && mysql $DB < "SET FOREIGN_KEY_CHECKS=1"
0

Simple et clair (peut être).

Ce n'est peut-être pas une solution sophistiquée, mais cela m'a fonctionné et m'a sauvé la journée.

Fonctionne avec la version serveur: 5.6.38 MySQL Community Server (GPL)

Les étapes que j'ai suivies:

 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

0
Sanjay Khadka

Cette solution est basée sur la réponse @SkyLeach mais prend en charge la suppression de tables avec des clés étrangères.

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
0
pgmank