空のテーブルを削除する方法


11

私の巨大なデータベース(mysql)からすべての空のテーブルを削除することは可能ですか?

空のテーブルをすべて自動的に削除するsqlコマンドを探しています。

現在、データセットには305のテーブルがあり、そのうちの約30%は古い空のテーブルであり、新しいアプリケーションでは使用されません。

明確にするために; すべてのテーブルはtype = MyISAMです。


1
すべてのテーブルはMyISAM、InnoDB、または両方の混合ですか???
RolandoMySQLDBA 2014

それらはすべてMyISAMです
qualbeen

回答:


11

アイデアはおそらく空のテーブルを探して INFORMATION_SCHEMA.TABLES

SELECT * 
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_ROWS =  '0'
AND TABLE_SCHEMA = 'my_database_only'

それからあなたはSQLクエリを生成することができるかもしれません

SELECT CONCAT('DROP TABLE ', GROUP_CONCAT(table_name), ';') AS query
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_ROWS = '0'
AND TABLE_SCHEMA = 'my_database_only';

速くて少し汚れていますが、実際に動作するはずです。


3
...そして、あなたはあなたのCONCATがスキーマ参照なしでテーブルリストを生成するという事実に加えて、mysqlシステムテーブルのいくつかを「おそらく」削除したので、あなたは壊れたデータベースサーバーを持っています。
クリスティアンポルタ

1
データベースの制限をテーブルにスマートに追加する「権利」もあります。
Tom Desp、2014

3
答えはユーザーにとって危険である可能性があるため、答えは当然のことと見なされるべきではありません...それだけです
Cristian Porta 14

2
1つのDROP TABLEコマンドを設定するための+1。
RolandoMySQLDBA 2014

1
@CP:わかりました。ひどい間違いです。そのため、回答を編集しました。ちなみに、SQLクエリが実際にMySQLシステムの内部テーブルをドロップする可能性があることには少し驚いています。私の観点からは、それは完全に壊れています。
Tom Desp、2014

7

すべてのテーブルがMyISAMであるため、これにより私の答えを表現しやすくなります。

まず、行がゼロのテーブルについてINFORMATION_SCHEMAをクエリする必要があります。

SELECT table_schema,table_name FROM information_schema.tables
WHERE table_rows = 0 AND table_schema NOT IN
('information_schema','mysql','performance_schema');

次に、クエリを作成して空のテーブルを削除します。

SELECT CONCAT('DROP TABLE ',table_schema,'.',table_name,';') DropTableCommand
FROM information_schema.tables
WHERE table_rows = 0 AND table_schema NOT IN
('information_schema','mysql','performance_schema');

次に、コマンドを外部SQLテキストファイルにダンプします。

SQL="SELECT CONCAT('DROP TABLE ',table_schema,'.',table_name,';') DropTableCommand"
SQL="${SQL} FROM information_schema.tables WHERE table_rows = 0 AND table_schema"
SQL="${SQL} NOT IN ('information_schema','mysql','performance_schema')"
mysql -uroot -p -ANe"${SQL}" > DropTables.sql

次のいずれかで内容を確認してください

  • less DropTables.sql
  • cat DropTables.sql

内容に満足したら、スクリプトを実行します。

mysql -uroot -p < DropTables.sql

またはmysqlにログインして、次のように実行します。

mysql> source DropTables.sql

試してみる !!!

警告:MyISAMテーブルの行数はテーブルのに物理的に格納されるため、この手法はMyISAMテーブルでのみ機能します.MYD。INFORMATION_SCHEMA.TABLESメタデータテーブルは常にこれを読み取り、更新しています。INNODBでこれを試さないでください!!!

UPDATE 2014-02-05 11:46 EST

除外した理由があります ('information_schema','mysql','performance_schema')

mysqlスキーマは、その中に空のテーブルを持っています。一部MyISAM、一部InnoDB、一部CSV

たとえば、これは私のデスクトップ上のMySQL 5.6.15のmysqlスキーマにある私のテーブルです

mysql> select table_name,engine,table_rows
    -> from information_schema.tables
    -> where table_schema='mysql';
+---------------------------+--------+------------+
| table_name                | engine | table_rows |
+---------------------------+--------+------------+
| columns_priv              | MyISAM |          0 |
| db                        | MyISAM |          2 |
| event                     | MyISAM |          0 |
| func                      | MyISAM |          0 |
| general_log               | CSV    |          2 |
| help_category             | MyISAM |         40 |
| help_keyword              | MyISAM |        485 |
| help_relation             | MyISAM |       1090 |
| help_topic                | MyISAM |        534 |
| innodb_index_stats        | InnoDB |          0 |
| innodb_table_stats        | InnoDB |          0 |
| ndb_binlog_index          | MyISAM |          0 |
| plugin                    | MyISAM |          0 |
| proc                      | MyISAM |          0 |
| procs_priv                | MyISAM |          0 |
| proxies_priv              | MyISAM |          1 |
| servers                   | MyISAM |          0 |
| slave_master_info         | InnoDB |          0 |
| slave_relay_log_info      | InnoDB |          0 |
| slave_worker_info         | InnoDB |          0 |
| slow_log                  | CSV    |          2 |
| tables_priv               | MyISAM |          0 |
| time_zone                 | MyISAM |          0 |
| time_zone_leap_second     | MyISAM |          0 |
| time_zone_name            | MyISAM |          0 |
| time_zone_transition      | MyISAM |          0 |
| time_zone_transition_type | MyISAM |          0 |
| user                      | MyISAM |          6 |
+---------------------------+--------+------------+
28 rows in set (0.01 sec)

mysql>

これらのテーブルのいくつかは(のように消えるとしたらcolumns_privproc_privtables_priv、など)、許可メカニズムが正常に動作しないことや、mysqldを引き起こす可能性が起動しません。mysql.procはストアドプロシージャの物理的なホームであるため、これを使いたくありません。mysqlスキーマ内のInnoDBテーブルを使用するCrashSafeレプリケーションなどのメカニズムを使用する場合、またはタイムゾーン情報を挿入する場合は、他のメカニズムが機能しない可能性があります。

UPDATE 2014-02-05 12:36 EST

特定の理由から、Tom Despが彼の回答賞賛したいと思います。彼の構文は、外部スクリプトを使用せずに削除できました。彼のアイデアを使用して、DROP TABLEコマンドをユーザー定義変数に取り込みます。

SELECT CONCAT('DROP TABLE ',GROUP_CONCAT(DBTB),';')
INTO @DropCommand
FROM (SELECT CONCAT(table_schema,'.',table_name) DBTB
FROM information_schema.tables
WHERE table_rows = 0 AND table_schema NOT IN
('information_schema','mysql','performance_schema')) A;
SELECT @DropCommand;

の出力SELECT @DropCommand;が正しい場合は、次のようなコマンドを実行します。

PREPARE s FROM @DropCommand;
EXECUTE s;
DEALLOCATE PREPARE s;

これにより、次の2つが排除されます。

  • 外部SQLテキストファイルの必要性
  • テーブルごとに個別のDROP TABLEコマンドを実行する

1
長くて良い説明をありがとう!データベース全体でテーブルを返す場合は+1。この方法では、複数のデータセットを簡単にクリーンアップできます。一方; 注意して使用してください。"..AND table_schema = 'my_database_name'"に対してクエリを実行して、1つのデータベースでのみ機能するようにします(Tom
Despが
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.