如何删除空表


11

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

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

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

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


1
是所有表都是MyISAM,InnoDB还是二者兼有?
RolandoMySQLDBA 2014年

他们都是MyISAM
qualbeen 2014年

Answers:


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
...然后您的数据库服务器坏了,因为您“可能”删除了一些mysql系统表...除了您的CONCAT生成没有模式引用的表列表的事实。
Cristian Porta

1
您还具有将表的数据库限制巧妙地添加到数据库的“权利”,我认为这很明显。
Tom Desp 2014年

3
答案不应该被认为是理所当然的,因为答案对用户有潜在的危险……仅此
Cristian Porta 2014年

2
+1用于设置单个DROP TABLE命令。
RolandoMySQLDBA'2

1
@CP:好吧,我的错误,这就是为什么我编辑答案的原因。顺便说一句,我对SQL查询实际上可以删除MySQL系统内部表感到有些惊讶。在我看来,这完全是无效的。
汤姆·德斯普

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

试试看 !!!

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>

如果某些这些表都是消失(如columns_privproc_privtables_priv,等),确认机制可能无法正常工作或可能造成的mysqld不启动。您也不想破坏mysql.proc,因为它是存储过程的物理位置。其他机制可能不起作用,或者是您想使用它们,例如使用mysql架构内的InnoDB表进行CrashSafe复制,或者要插入时区信息。

更新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;

这消除了两件事:

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

1
感谢您长期而良好的解释!+1用于跨数据库返回表。这样很容易清理几个数据集。另一方面; 小心使用。我针对“ ..AND table_schema ='my_database_name'”运行查询,以仅使用一个数据库(如Tom Desp在另一
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.