If you’ve ever installed some 3rd party software on you website (eg: phpbb forum), you certainly know that database tables, created during that process, generally have a convenient prefix in their names (default one for phpBB is phpbb_). This is done, I believe, to make sure that all of application’s tables get grouped together and do not mix with your previously created ones.

There are situations when you’d want to remove such grouped tables, all of them at once – for example, when, several days ago, I obtained our latest UMapper SQL-dump I, unfortunately, forgot to ignore forum tables, so they got into my localhost box. Today, I spotted those and wondered how can I quickly get rid of them. As I really like to work with MySQL via CLI, the question raised – how to remove multiple tables using single query.

At first, I tried to use LIKE clause the way it is used in SHOW TABLES:

mysql> SHOW TABLES LIKE "phpbb_%"; /* list all phpBB tables */
mysql> DROP TABLES LIKE "phpbb_%"; /* DROP THEM? Quite a naive approach.. */

Well, even before executing it I was 99% sure that this “method” wouldn’t work. Indeed, it didn’t :)

I certainly knew that you can drop several tables at once if you list all of them separated with commas:

mysql> DROP TABLE phpbb_zebra, phpbb_words; /* DROP several tables*/

So, I decided that it would be good enough if I form a query which would generate yet another query that would drop all similarly prefixed tables. If it’s not already, it would be crystal clear what I mean in a minute.

To get list of tables complying to certain criteria one could use information_schema database. To get list of all phpbb_ prefixed tables we can issue something like this:

mysql> SELECT GROUP_CONCAT(TABLE_NAME) 
           FROM information_schema.TABLES 
           WHERE TABLE_SCHEMA = "your_db_name" AND TABLE_NAME LIKE "phpbb_%";

Result (line-breaks added for readability):

phpbb_acl_groups,phpbb_acl_options,phpbb_acl_roles,phpbb_acl_roles_data,
phpbb_acl_users,phpbb_attachments,phpbb_banlist,phpbb_bbcodes,phpbb_bookmarks,
SKIPPED
phpbb_search_results,phpbb_search_wordlist,phpbb_search_wordmatch,phpbb_sessions,
phpbb_sessions_keys,phpbb_sitelist,phpbb_smilies,phpbb_styles,phpbb_styles_imageset,

Going from here, the only thing we need is to prepend the result with DROP TABLE string:

mysql> SELECT 
           CONCAT(
                  "DROP TABLE ",  
                   GROUP_CONCAT(TABLE_NAME)
           ) AS stmt 
           FROM information_schema.TABLES 
           WHERE TABLE_SCHEMA = "your_db_name" AND TABLE_NAME LIKE "phpbb_%";

Then, actually removing tables is a matter of copy-pasting the generated query.

That’s it! If you know a better way, please, share in comments!

P.S. It only occurred to me that I relied on two queries for doing the job, albeit second one was simply copy-pasted.

    ,
    Trackback

    4 comments untill now

    1. Thanks!

      Exactly what I needed.

    2. Sometimes you will encounter to drop table many tables with lengthy names and it will be possible to excess the default length of group_concat can return . You can just edit the config file of mysql or make use of the function below to work-around this:
      function drop_tables($host , $user , $password , $dbname , $prefix = ”)
      {

      $con = mysql_connect($host , $user , $password );
      if (!$con)
      {
      die(‘Could not connect: ‘ . mysql_error());
      }
      $array = array();
      $sql = “SELECT table_name
      FROM information_schema.TABLES
      WHERE TABLE_SCHEMA = ‘$dbname’ “;
      if(empty($prefix))
      $sql .= “AND TABLE_NAME LIKE ‘%%’”;
      else
      $sql .= “AND TABLE_NAME LIKE ‘$prefix%’”;

      $result = mysql_query($sql,$con) or die( mysql_error());
      while($row = mysql_fetch_assoc($result))
      {
      $array[] = $row['table_name'];
      }

      $sql = “DROP table “.implode(“,” , $array);

      mysql_close($con);

      return $sql;

      }

    3. If you have shell access try this simple script:

      create a ~/.my.cnf with:

      [client]
      user = dbuserid
      password = dbpassword
      host = mysql_server

      [mysql]
      database = dbname

      Now create the following shell script:

      drop_tables.sh
      #!/usr/bin/tcsh

      if ($#argv != 1) then
      echo “Usage: $0 table_prefix”
      echo e.g. $0 wp
      exit 1
      endif

      foreach i ( `mysql -e “show tables like ‘$1_%’” | grep -v Tables_in_ ` )
      echo mysql -e “drop table $i”
      mysql -e “drop table $i”
      end

      exit 0

      Handy for clearing out joomla and wordpress installs

    4. Hi,

      if you can use php try this:

      $delete_array = mysql_query(“SHOW TABLE STATUS LIKE ‘x__%’”);
      while ($delete = mysql_fetch_array($delete_array)) {
      mysql_query(“DROP TABLE ” . $delete['Name']);
      }

      greetz

      Rene

    Add your comment now