如何删除空表

qua*_*een 13 mysql myisam

是否可以从我的庞大数据库 (mysql) 中删除所有空表?

我正在寻找一个 sql 命令来自动删除所有这些空表。

目前,我的数据集中有 305 个表,其中大约 30% 是旧的空表,不会在我的新应用程序中使用。

只是为了澄清;所有表的类型都是=MyISAM

Tom*_*esp 14

这个想法可能是使用 INFORMATION_SCHEMA.TABLES

SELECT * 
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_ROWS =  '0'
AND TABLE_SCHEMA = 'my_database_only'
Run Code Online (Sandbox Code Playgroud)

然后你可能能够生成一个 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';
Run Code Online (Sandbox Code Playgroud)

快速且有点脏,但实际上应该可以工作。

  • ...然后你有一个损坏的数据库服务器,因为你“可能”删除了一些 mysql 系统表......除了你的 CONCAT 生成一个没有模式引用的表列表的事实。 (3认同)
  • 答案不应该认为任何事情都是理所当然的,因为答案对用户有潜在危险……仅此而已 (3认同)
  • +1 用于设置单个 DROP TABLE 命令。 (2认同)

Rol*_*DBA 9

由于所有表都是 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');
Run Code Online (Sandbox Code Playgroud)

接下来,制定查询以删除空表:

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');
Run Code Online (Sandbox Code Playgroud)

现在,将命令转储到外部 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
Run Code Online (Sandbox Code Playgroud)

用以下之一查看内容

  • less DropTables.sql
  • cat DropTables.sql

如果您对其内容感到满意,请运行脚本:

mysql -uroot -p < DropTables.sql
Run Code Online (Sandbox Code Playgroud)

或登录到 mysql 并像这样运行它:

mysql> source DropTables.sql
Run Code Online (Sandbox Code Playgroud)

试一试 !!!

CAVEAT:此技术仅适用于 MyISAM 表,因为 MyISAM 表的行数物理存储在.MYD表中。INFORMATION_SCHEMA.TABLES 元数据表一直在读取和更新。不要用 INNODB 尝试这个!!!

更新 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>
Run Code Online (Sandbox Code Playgroud)

如果其中一些表消失(如columns_privproc_privtables_priv等),则授权机制可能无法正常工作或可能导致 mysqld 无法启动。你也不想重击 mysql.proc 因为它是存储过程的物理家。如果您想使用其他机制,例如使用 mysql 架构内的 InnoDB 表的 CrashSafe 复制,或者如果您想插入时区信息,则其他机制可能不起作用。

更新 2014-02-05 12:36 美国东部时间

我想赞扬 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;
Run Code Online (Sandbox Code Playgroud)

如果输出SELECT @DropCommand;正确,则执行如下命令:

PREPARE s FROM @DropCommand;
EXECUTE s;
DEALLOCATE PREPARE s;
Run Code Online (Sandbox Code Playgroud)

这消除了两件事:

  • 需要外部 SQL 文本文件
  • 为每个表运行单独的 DROP TABLE 命令