如何从MySQL数据库中删除所有空表,只留下至少有1条记录的表?
答案 0 :(得分:3)
此存储过程应该这样做:
DELIMITER $$
DROP PROCEDURE IF EXISTS `drop_empty_tables_from` $$
CREATE PROCEDURE `drop_empty_tables_from`(IN schema_target VARCHAR(128))
BEGIN
DECLARE table_list TEXT;
DECLARE total VARCHAR(11);
SELECT
GROUP_CONCAT(`TABLE_NAME`),
COUNT(`TABLE_NAME`)
INTO
table_list,
total
FROM `information_schema`.`TABLES`
WHERE
`TABLE_SCHEMA` = schema_target
AND `TABLE_ROWS` = 0;
IF table_list IS NOT NULL THEN
SET @drop_tables = CONCAT("DROP TABLE ", table_list);
PREPARE stmt FROM @drop_tables;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END IF;
SELECT total AS affected_tables;
END $$
DELIMITER ;
当空表太多时,GROUP_CONCAT
可能会出现问题。它取决于group_concat_max_len
系统变量的值。
在一个查询中无法执行此操作,因为DROP TABLE
无法从SELECT
查询中接收其参数。
感谢 James 的评论。在InnoDB表的情况下,行计数查询似乎不会返回精确的结果,因此当该模式中存在InnoDB表时,上述过程不能保证完美地工作。
对于InnoDB表,行数是 只是在SQL中使用的粗略估计 优化。 (如果是这样的话也是如此 InnoDB表是分区的。)
答案 1 :(得分:3)
使用Percona Toolkit中的pt-find:
$ pt-find --dblike "mydatabase" --empty --exec-plus "DROP TABLE %s"
答案 2 :(得分:2)
完整性的PHP版本。它不会丢弃任何东西,只为你打印DROP语句:
<?php
$username="root";
$password="mypassword";
$database="mydatabase";
mysql_connect('localhost',$username,$password);
mysql_select_db($database) or die( "Unable to select database");
function drop_empty_tables(){
$tables = mysql_query('SHOW TABLES');
while($table = mysql_fetch_array($tables)){
$table = $table[0];
$records = mysql_query("SELECT * FROM $table");
if(mysql_num_rows($records) == 0){
// mysql_query("DROP TABLE $table");
echo "DROP TABLE $table;\n";
}
}
}
drop_empty_tables();
?>
答案 3 :(得分:1)
IF (SELECT * FROM tablexy) DROP TABLE tablexy
IF (SELECT * FROM tablexy) DROP TABLE tablexy
(您必须为每个表运行此查询,因为我没有找到在一个查询中对所有表执行一个查询的方法)
这是相同的查询,但我想与NOTHING和SOMETHING没有任何内容;)
答案 4 :(得分:1)
这是之前发布的php脚本的修改版本,
我添加了一个循环遍历所有数据库的函数(当你想要运行真实的脚本时,作为原始脚本,取消注释mysql_query())
<?php
$username="root";
$password="mypassword";
$database="information_schema";
mysql_connect('localhost',$username,$password);
mysql_select_db($database) or die( "Unable to select database\n");
function find_databases() {
// edit the query if you want to add more databases that you dont want to mess with
$databaseq = mysql_query("SELECT DISTINCT(SCHEMA_NAME) FROM SCHEMATA WHERE SCHEMA_NAME not in ('information_schema','mysql','phpmyadmin');");
while($databaser = mysql_fetch_array($databaseq)){
echo "Checking $databaser[0] ...\n";
drop_empty_tables_and_db($databaser[0]);
}
}
function drop_empty_tables_and_db($get_database){
mysql_select_db($get_database) or print( "Unable to select database $get_databas\n");
$tables = mysql_query('SHOW TABLES');
while($table = mysql_fetch_array($tables)){
$table = $table[0];
$records = mysql_query("SELECT * FROM $table");
if(mysql_num_rows($records) == 0){
echo "DROP TABLE `$table`; \n";
//mysql_query("DROP TABLE `$table`") or print( "Unable to drop table $table\n");
}
}
$tables = mysql_query('SHOW TABLES');
if(mysql_num_rows($tables) == 0){
echo "DROP DATABASE `$get_database`;\n";
//mysql_query("DROP DATABASE `$get_database`") or print( "Unable to drop database $get_database\n");
}
}
find_databases(); //...and remove them :)
?>
答案 5 :(得分:1)
如果直接从shell使用,请将db替换为database_name。请注意,这是现场直播,不需要注释。
db='wordpress_db';
for f in $(mysql -e "use $db;SHOW TABLES;" | sed 's/^| \([^ ]*\).*$/\1/g'|sed 1d);
do
c=`mysql -e "use $db;SELECT COUNT(*) FROM ${f}\G"|sed '/:/!d; s/^[^:]*: //g'`;
[[ $c == 0 ]] && { echo "DROP db.$f" && mysql -e "use $db;DROP TABLE $f"; }
done
答案 6 :(得分:0)
我不熟悉存储过程。因此我选择避免它们。 最后我用Python使用MySQL做了它,PHP非常相似:
import MySQLdb
conn = MySQLdb.connect(
host='localhost',
user='root',
passwd='mypassword',
db='mydatabase'
)
c = conn.cursor()
c.execute('SHOW TABLES')
for table in c.fetchall():
c.execute('SELECT * FROM %s' % table[0])
if c.rowcount == 0:
c.execute('DROP TABLE %s' % table[0])
答案 7 :(得分:0)
使用PHP的另一种方法是:
#connect to database first
$sql = "SHOW TABLE STATUS FROM `".$database."`
WHERE ENGINE IS NOT NULL
AND `Rows`=0";
if($res = mysql_query($sql)){
if(mysql_numrows($res)){
while($r = mysql_fetch_assoc($res)){
$table = $r['Name'];
echo '<br />'.$table;
if($ret = mysql_query("DROP TABLE `".$table."`")){
echo ' = DROPPED';
}else{
echo ' = '.mysql_error();
}
}
}
}
这将删除另一个执行只是为了确定该表没有行。
我使用存储过程遇到了GROUP_CONCAT
的问题。奇怪的是,有些表格未被识别,似乎找不到它们。
答案 8 :(得分:0)
尝试:
$tables = $conn->query('SHOW TABLES');
$i = 0;
while($table = $tables->fetch_array(MYSQLI_NUM)){
$table = $table[0];
$records = $conn->query("SELECT * FROM `$table`");
if($records->num_rows == 0){
if ($conn->query(" DROP TABLE `$table` ")){
$i++;
}
}
}
return $i;
变量$ i显示已删除的表计数