MySQL: DROP TABLE commençant par un préfixe

8

EXEMPLE: J'ai plus de 30 tables commençant par un préfixe "dp_" et environ 12 commençant par "ex_".

QUESTION: Comment puis-je supprimer toutes les tables commençant par "dp_" dans une seule requête?

poelinca
la source
J'ai mis à jour ma réponse pour effectuer la suppression des tables sans utiliser de procédure stockée. Essaie !!!
RolandoMySQLDBA

Réponses:

11

Voici une procédure stockée qui accepte la base de données et la chaîne de préfixe comme paramètres:

DELIMITER $$

DROP PROCEDURE DropTablesWithPrefix $$
CREATE PROCEDURE DropTablesWithPrefix(db VARCHAR(64),prfx VARCHAR(20))
StoredProcedure:BEGIN
    DECLARE ndx,maxidx INT;
    DECLARE giventable,SQLSTMT VARCHAR(500);

    CREATE TABLE TableZapList
    (
        droptablesql VARCHAR(512),
        idx INT NOT NULL AUTO_INCREMENT PRIMARY KEY
    ) ENGINE=MyISAM;

    INSERT INTO TableZapList (droptablesql)
    SELECT CONCAT('DROP TABLE ',table_schema,'.',table_name)
    FROM information_schema.tables
    WHERE table_schema = db AND SUBSTR(table_name,LENGTH(prfx)) = prfx;
    SELECT COUNT(1) INTO maxid FROM TableZapList;

    IF maxid = 0 THEN
        LEAVE StoredProcedure;
    END IF;<BR>

    SET ndx = 0;
    WHILE ndx < maxid DO
        SET ndx = ndx + 1;
        SELECT droptablesql INTO SQLSTMT FROM TableZapList WHERE idx = ndx;
        SET @sql = SQLSTMT;
        PREPARE stmt FROM @sql;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
    END WHILE;<BR>

    SELECT droptablesql FROM TableZapList;
    DROP TABLE TableZapList;
END;

DELIMITER ;

MISE À JOUR 2011-07-12 14:55 EDT

Je viens de penser à une manière plus propre et simpliste. Au lieu d'utiliser une procédure stockée, utilisez simplement la fonction GROUP_CONCAT pour rassembler toutes les tables à zapper. Composez ensuite en une seule requête:

Voici une requête pour supprimer toutes les tables commençant par wp_pol dans la base de données actuelle:

SELECT CONCAT('DROP TABLE ',GROUP_CONCAT(CONCAT(table_schema,'.',table_name)),';')
FROM information_schema.tables
WHERE table_schema=database()
AND table_name like 'wp_pol%';

La prochaine chose à faire est d'en stocker le résultat dans

SELECT CONCAT('DROP TABLE ',GROUP_CONCAT(CONCAT(table_schema,'.',table_name)),';')
INTO @dropcmd
FROM information_schema.tables
WHERE table_schema=database()
AND table_name like 'wp_pol%';

La dernière chose est d'exécuter le SQL dynamique en utilisant ces trois (3) commandes:

PREPARE s1 FROM @dropcmd;
EXECUTE s1;
DEALLOCATE PREPARE s1;

Voici une démonstration utilisant MySQL 5.5.12 sous Windows qui fonctionne:

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 11
Server version: 5.5.12 MySQL Community Server (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

MySQL (Current test) :: use garbage
Database changed
MySQL (Current garbage) :: show tables;
+------------------------------+
| Tables_in_garbage            |
+------------------------------+
| datas                        |
| rolando                      |
| wp_commentmeta               |
| wp_comments                  |
| wp_contact_form_7            |
| wp_links                     |
| wp_most_read_hits            |
| wp_options                   |
| wp_pollsa                    |
| wp_pollsip                   |
| wp_pollsq                    |
| wp_postmeta                  |
| wp_posts                     |
| wp_posts_idtracker           |
| wp_tantan_wordpress_s3_cache |
| wp_term_relationships        |
| wp_term_taxonomy             |
| wp_terms                     |
| wp_usermeta                  |
| wp_users                     |
| wp_w3tc_cdn_queue            |
+------------------------------+
21 rows in set (0.00 sec)

MySQL (Current garbage) :: SELECT CONCAT('DROP TABLE ',GROUP_CONCAT(CONCAT(table_schema,'.',table_name)),';') INTO @dropcmd FROM information_schema.tables WHERE table_schema=database() AND table_name like 'wp_pol%';
Query OK, 1 row affected (0.00 sec)

MySQL (Current garbage) :: SELECT @dropcmd;
+--------------------------------------------------------------------+
| @dropcmd                                                           |
+--------------------------------------------------------------------+
| DROP TABLE garbage.wp_pollsa,garbage.wp_pollsip,garbage.wp_pollsq; |
+--------------------------------------------------------------------+
1 row in set (0.00 sec)

MySQL (Current garbage) :: PREPARE s1 FROM @dropcmd; EXECUTE s1; DEALLOCATE PREPARE s1;
Query OK, 0 rows affected (0.00 sec)
Statement prepared

Query OK, 0 rows affected (0.01 sec)

Query OK, 0 rows affected (0.00 sec)

MySQL (Current garbage) :: show tables;
+------------------------------+
| Tables_in_garbage            |
+------------------------------+
| datas                        |
| rolando                      |
| wp_commentmeta               |
| wp_comments                  |
| wp_contact_form_7            |
| wp_links                     |
| wp_most_read_hits            |
| wp_options                   |
| wp_postmeta                  |
| wp_posts                     |
| wp_posts_idtracker           |
| wp_tantan_wordpress_s3_cache |
| wp_term_relationships        |
| wp_term_taxonomy             |
| wp_terms                     |
| wp_usermeta                  |
| wp_users                     |
| wp_w3tc_cdn_queue            |
+------------------------------+
18 rows in set (0.00 sec)

MySQL (Current garbage) ::

Essaie !!!

RolandoMySQLDBA
la source
Le script Rolandos fonctionne mais il peut être nécessaire d'augmenter le paramètre group_concat_max_len si vous avez beaucoup de tables ou des noms de table très longs: SET SESSION group_concat_max_len = 1000000;
JohnP
Au lieu de changer groupe + concat_max_len, j'ai utilisé une sous-requête avec une limite et effectué les baisses par étapes
pedromanoel
La SUBSTRcondition dans le INSERTdevrait être: SUBSTR(table_name, 1, LENGTH(prfx)) = prfxalors ça marche bien.
laurent
8

Tout d'abord, générez un script pour ce faire à l'invite Unix:

$  echo "select concat('drop table ', table_name, ';') from information_schema.tables where table_name like 'prefix_%';" |mysql --user=root --password=blah --batch >drop.sql

Remplacez le préfixe par le vôtre. L' --batchoption supprime le formatage sophistiqué que MySQL fait par défaut afin que vous puissiez produire un script SQL exécutable.

Passez en revue le script et s'il semble OK, exécutez drop.sqlà l' mysql>invite.

Gaius
la source
j'ai déjà fait un script d'aide php pour ce faire, mais je me demandais si cela pouvait être fait en utilisant une seule requête.
poelinca
1
Réponse simple: Non. Réponse complexe: Oui, si vous l'enveloppez dans une procédure stockée . Vous pouvez donc l'exécuter en une seule commande, mais ce serait la même chose que d'appeler un script.
Gaius
4

Vous devez interroger les tables système pour ces noms de table et créer une chaîne pour l'exécuter dynamiquement. Dans SQL Server, je ferais quelque chose comme:

declare @x varchar(max), @enter char(2);
select @x = '', @enter = char(13)+char(10);

Select @x = @x + 'drop table ' + table_name + ';' + @enter    
from information_schema.tables    
where table_name like '%accounting%'

print @x
execute (@x);

Vous devez maintenant trouver la table système correspondante dans MySQL.

Marian
la source
J'ai lu votre réponse très attentivement. C'est aussi ma réponse. Bien qu'en dialecte SQL Server, votre réponse est, en principe, la première bonne réponse. +1 !!!
RolandoMySQLDBA
3

Pour répondre à votre question, non. Pas dans MySQL en utilisant une seule commande / requête. Vous devrez enchaîner les commandes.

Cependant, si vous souhaitez atteindre votre objectif, voici une façon:

À partir d'un script bash, quelque chose comme:

#/bin/bash
TABLES=`mysql -s -e "SELECT CONCAT(TABLE_SCHEMA,'.',TABLE_NAME) AS T FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE 'dp_%'" -u user -p`

for i in $TABLES; 
do 
 echo "DROP TABLE $i;" >> drops.sql ; 
done

cat drops.sql

Examinez ensuite le fichier drops.sql. Si tout va bien, faites une SAUVEGARDE , puis ...

mysql -u username -p -v --show-warnings < drops.sql
randomx
la source
1

Vous pouvez toujours utiliser un ADMINISTRATEUR DE BASE DE DONNÉES comme navicat et ce genre de problèmes disparaîtra avec une simple sélection et suppression.

Nestor Gonzalez
la source