有没有一种简便的方法可以从MySQL数据库中删除所有表,忽略可能存在的任何外键约束?
有没有一种简便的方法可以从MySQL数据库中删除所有表,忽略可能存在的任何外键约束?
我发现生成的drop语句集非常有用,推荐进行以下改进:
SELECT concat('DROP TABLE IF EXISTS `', table_name, '`;')
FROM information_schema.tables
WHERE table_schema = 'MyDatabaseName';
注意1:这并不会执行DROP语句,它只会给你一个列表。你需要将输出剪切粘贴到你的SQL引擎中来执行。
注意2:如果你有视图(VIEWs),你需要手动将每个DROP TABLE `VIEW_NAME`
语句更正为DROP VIEW `VIEW_NAME`
。
"RESTRICT和CASCADE被允许以使移植更容易。在MySQL 5.5中,它们什么也不做。"
因此,如果你需要删除语句起作用,你需要:
SET FOREIGN_KEY_CHECKS = 0
这将禁用引用完整性检查 - 所以当你完成所需的删除操作后,你需要重置关键检查,使用以下命令:
SET FOREIGN_KEY_CHECKS = 1
SET FOREIGN_KEY_CHECKS = 0;
-- Your semicolon separated list of DROP statements here
SET FOREIGN_KEY_CHECKS = 1;
注意:为了更轻松地使用SELECT语句的输出,可以使用mysql -B选项。
DROP DATABASE foo; CREATE DATABASE foo;
,虽然不完全相同,但对我有用。 - Timmmm来自http://www.devdaily.com/blog/post/mysql/drop-mysql-tables-in-any-order-foreign-keys:
SET FOREIGN_KEY_CHECKS = 0;
drop table if exists customers;
drop table if exists orders;
drop table if exists order_details;
SET FOREIGN_KEY_CHECKS = 1;
(请注意,这个回答解决的是如何禁用外键检查,以便能够任意顺序删除表格。它不是回答如何自动生成所有现有表格的drop-table语句并在单个脚本中执行它们。 Jean的回答可以解决这个问题。)
这里是SurlyDre的存储过程,已经修改为忽略外键:
DROP PROCEDURE IF EXISTS `drop_all_tables`;
DELIMITER $$
CREATE PROCEDURE `drop_all_tables`()
BEGIN
DECLARE _done INT DEFAULT FALSE;
DECLARE _tableName VARCHAR(255);
DECLARE _cursor CURSOR FOR
SELECT table_name
FROM information_schema.TABLES
WHERE table_schema = SCHEMA();
DECLARE CONTINUE HANDLER FOR NOT FOUND SET _done = TRUE;
SET FOREIGN_KEY_CHECKS = 0;
OPEN _cursor;
REPEAT FETCH _cursor INTO _tableName;
IF NOT _done THEN
SET @stmt_sql = CONCAT('DROP TABLE ', _tableName);
PREPARE stmt1 FROM @stmt_sql;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
END IF;
UNTIL _done END REPEAT;
CLOSE _cursor;
SET FOREIGN_KEY_CHECKS = 1;
END$$
DELIMITER ;
call drop_all_tables();
DROP PROCEDURE IF EXISTS `drop_all_tables`;
_tableName
。否则,在某些表格(如“group”或其他关键字)上将无法正常运行。 - sashaaero据我所知,以上每种方法都比这种方法需要更多的工作...
( mysqldump --add-drop-table --no-data -u root -p database | grep 'DROP TABLE' ) > ./drop_all_tables.sql
mysql -u root -p database < ./drop_all_tables.sql
mysqldump
的输出通过管道传递给 mysql
,而不需要通过文件来传递? - Rolfmysqldump
的输出通过管道传递给 grep
再传递给 mysql
,现在可以正常运行了。再次感谢您的解决方案,非常好。 - Rolf从这个答案中得知:
执行:
use `dbName`; --your db name here
SET FOREIGN_KEY_CHECKS = 0;
SET @tables = NULL;
SET GROUP_CONCAT_MAX_LEN=32768;
SELECT GROUP_CONCAT('`', table_schema, '`.`', table_name, '`') INTO @tables
FROM information_schema.tables
WHERE table_schema = (SELECT DATABASE());
SELECT IFNULL(@tables, '') INTO @tables;
SET @tables = CONCAT('DROP TABLE IF EXISTS ', @tables);
PREPARE stmt FROM @tables;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET FOREIGN_KEY_CHECKS = 1;
这将从当前使用的数据库中删除表。您可以使用use
设置当前数据库。
或者,Dion的答案更简单,但您需要执行两次,首先获取查询,然后执行查询。我提供了一些愚蠢的反引号来转义db和表名称中的特殊字符。
SELECT CONCAT('DROP TABLE IF EXISTS `', table_schema, '`.`', table_name, '`;')
FROM information_schema.tables
WHERE table_schema = 'dbName'; --your db name here
empty
WHERE 0=1',
CONCAT('DROP TABLE IF EXISTS ', @tables)) INTO @tables; - Mirco Babin这里是基于游标的解决方案。比较冗长但可以作为单个SQL批次运行:
DROP PROCEDURE IF EXISTS `drop_all_tables`;
DELIMITER $$
CREATE PROCEDURE `drop_all_tables`()
BEGIN
DECLARE _done INT DEFAULT FALSE;
DECLARE _tableName VARCHAR(255);
DECLARE _cursor CURSOR FOR
SELECT table_name
FROM information_schema.TABLES
WHERE table_schema = SCHEMA();
DECLARE CONTINUE HANDLER FOR NOT FOUND SET _done = TRUE;
OPEN _cursor;
REPEAT FETCH _cursor INTO _tableName;
IF NOT _done THEN
SET @stmt_sql = CONCAT('DROP TABLE ', _tableName);
PREPARE stmt1 FROM @stmt_sql;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
END IF;
UNTIL _done END REPEAT;
CLOSE _cursor;
END$$
DELIMITER ;
call drop_all_tables();
DROP PROCEDURE IF EXISTS `drop_all_tables`;
删除指定数据库中所有表的一行命令:
echo "DATABASE_NAME"| xargs -I{} sh -c "mysql -Nse 'show tables' {}| xargs -I[] mysql -e 'SET FOREIGN_KEY_CHECKS=0; drop table []' {}"
运行此命令将从数据库DATABASE_NAME中删除所有表。
而且,这个好处是数据库名称只需显式写一次。
你可以这样做:
select concat('drop table if exists ', table_name, ' cascade;')
from information_schema.tables;
接下来运行生成的查询语句。它们会删除当前数据库中的每个表。
这里提供了有关drop table
命令的帮助。
||
被设置为连接运算符。更具体地说,MySQL SQL 模式包含 PIPES_AS_CONCAT
。参考:http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html#sqlmode_pipes_as_concat - Ionuț G. Stanconcat
代替||
。 - Pablo Santa Cruz使用存储过程实现从 SQL Select 查询中一步完成而无需复制返回值的解决方案。
SET FOREIGN_KEY_CHECKS = 0;
SET SESSION group_concat_max_len = 1000000;
SET @TABLES = NULL;
SELECT GROUP_CONCAT('`', table_schema, '`.`', table_name,'`') INTO @TABLES FROM information_schema.tables
WHERE table_schema = 'databaseName';
SET @TABLES = CONCAT('DROP TABLE IF EXISTS ', @TABLES);
PREPARE stmt FROM @TABLES;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET SESSION group_concat_max_len = 1024;
SET FOREIGN_KEY_CHECKS = 1
每次搜索特定主题时,Google都会把我导向这个Stack Overflow的问题,因此在这里提供可以删除表格和视图的MySQL代码:
DROP PROCEDURE IF EXISTS `drop_all_tables`;
DELIMITER $$
CREATE PROCEDURE `drop_all_tables`()
BEGIN
DECLARE _done INT DEFAULT FALSE;
DECLARE _tableName VARCHAR(255);
DECLARE _cursor CURSOR FOR
SELECT table_name
FROM information_schema.TABLES
WHERE table_schema = SCHEMA();
DECLARE CONTINUE HANDLER FOR NOT FOUND SET _done = TRUE;
SET FOREIGN_KEY_CHECKS = 0;
OPEN _cursor;
REPEAT FETCH _cursor INTO _tableName;
IF NOT _done THEN
SET @stmt_sql1 = CONCAT('DROP TABLE IF EXISTS ', _tableName);
SET @stmt_sql2 = CONCAT('DROP VIEW IF EXISTS ', _tableName);
PREPARE stmt1 FROM @stmt_sql1;
PREPARE stmt2 FROM @stmt_sql2;
EXECUTE stmt1;
EXECUTE stmt2;
DEALLOCATE PREPARE stmt1;
DEALLOCATE PREPARE stmt2;
END IF;
UNTIL _done END REPEAT;
CLOSE _cursor;
SET FOREIGN_KEY_CHECKS = 1;
END$$
DELIMITER ;
call drop_all_tables();
DROP PROCEDURE IF EXISTS `drop_all_tables`;