有没有一种简单的方法可以从 MySQL 数据库中删除所有表,而忽略其中可能存在的任何外键约束?
26 回答
我发现生成的 drop 语句集很有用,并推荐以下调整:
- 将生成的 drop 限制在您的数据库中,如下所示:
SELECT concat('DROP TABLE IF EXISTS `', table_name, '`;')
FROM information_schema.tables
WHERE table_schema = 'MyDatabaseName';
注意 1:这不会执行 DROP 语句,它只是为您提供它们的列表。您需要将输出剪切并粘贴到 SQL 引擎中以执行它们。
注意 2:如果您有 VIEW,则必须手动更正每个DROP TABLE `VIEW_NAME`
语句。DROP VIEW `VIEW_NAME`
- 请注意,根据http://dev.mysql.com/doc/refman/5.5/en/drop-table.html,级联删除是没有意义的/具有误导性的:
“允许 RESTRICT 和 CASCADE 使移植更容易。在 MySQL 5.5 中,它们什么都不做。”
因此,如果您需要,为了使 drop 语句起作用:
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 选项会有所帮助。
来自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;
(请注意,这回答了如何禁用外键检查以便能够以任意顺序删除表。它没有回答如何为所有现有表自动生成删除表语句并在单个脚本中执行它们。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`;
上面的每一种方法都比这一种 AFAICT 包括更多的工作......
( 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
从这个答案,
执行:
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 接受的答案更简单,只是您需要执行两次,第一次是获取查询,第二次是执行查询。我提供了一些愚蠢的反引号来转义数据库和表名中的特殊字符。
SELECT CONCAT('DROP TABLE IF EXISTS `', table_schema, '`.`', table_name, '`;')
FROM information_schema.tables
WHERE table_schema = 'dbName'; --your db name here
这是一个基于光标的解决方案。有点长,但作为单个 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`;
你可以做:
select concat('drop table if exists ', table_name, ' cascade;')
from information_schema.tables;
然后运行生成的查询。他们将删除当前数据库中的每一个表。
这里有一些关于drop table
命令的帮助。
从给定数据库中删除所有表的单行:
echo "DATABASE_NAME"| xargs -I{} sh -c "mysql -Nse 'show tables' {}| xargs -I[] mysql -e 'SET FOREIGN_KEY_CHECKS=0; drop table []' {}"
运行此命令将从数据库 DATABASE_NAME 中删除所有表。
这样做的好处是数据库名称只显式写入一次。
我对 Dion Truter 的回答提出了这个修改,以使许多表格更容易:
SET GROUP_CONCAT_MAX_LEN = 10000000;
SELECT CONCAT('SET FOREIGN_KEY_CHECKS=0;\n',
GROUP_CONCAT(CONCAT('DROP TABLE IF EXISTS `', table_name, '`')
SEPARATOR ';\n'),
';\nSET FOREIGN_KEY_CHECKS=1;')
FROM information_schema.tables
WHERE table_schema = 'SchemaName';
这会在一个字段中返回整个内容,因此您可以复制一次并删除所有表(Copy Field Content (unquoted)
在 Workbench 中使用)。如果你有很多表,你可能会遇到一些限制GROUP_CONCAT()
。如果是这样,请增加 max len 变量(以及max_allowed_packet
,如果需要)。
无需使用过程从 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
谷歌搜索主题总是让我想到这个 SO 问题,所以这里是删除两个表和视图的工作 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`;
这是通过 bash 脚本自动执行此操作的方法:
host=$1
dbName=$2
user=$3
password=$4
if [ -z "$1" ]
then
host="localhost"
fi
# drop all the tables in the database
for i in `mysql -h$host -u$user -p$password $dbName -e "show tables" | grep -v Tables_in` ; do echo $i && mysql -h$host -u$user -p$password $dbName -e "SET FOREIGN_KEY_CHECKS = 0; drop table $i ; SET FOREIGN_KEY_CHECKS = 1" ; done
如果在 linux(或任何其他支持管道、echo 和 grep 的系统)中,你可以用一行来完成:
echo "SET FOREIGN_KEY_CHECKS = 0;" > temp.txt; \
mysqldump -u[USER] -p[PASSWORD] --add-drop-table --no-data [DATABASE] | grep ^DROP >> temp.txt; \
echo "SET FOREIGN_KEY_CHECKS = 1;" >> temp.txt; \
mysql -u[USER] -p[PASSWORD] [DATABASE] < temp.txt;
我知道这是一个老问题,但我认为这种方法既快速又简单。
使用命令行中的一行从数据库中删除所有表:
mysqldump -u [user_name] -p[password] -h [host_name] --add-drop-table --no-data [database_name] | grep ^DROP | mysql -u [user_name] -p[password] -h [host_name] [database_name]
其中 [user_name]、[password]、[host_name] 和 [database_name] 必须替换为真实数据(用户、密码、主机名、数据库名)。
在 php 中它很简单:
$pdo = new PDO('mysql:dbname=YOURDB', 'root', 'root');
$pdo->exec('SET FOREIGN_KEY_CHECKS = 0');
$query = "SELECT concat('DROP TABLE IF EXISTS ', table_name, ';')
FROM information_schema.tables
WHERE table_schema = 'YOURDB'";
foreach($pdo->query($query) as $row) {
$pdo->exec($row[0]);
}
$pdo->exec('SET FOREIGN_KEY_CHECKS = 1');
只要记住将 YOURDB 更改为您的数据库的名称,显然是用户/密码。
在像 bash/zsh 这样的 Linux shell 中:
DATABASE_TO_EMPTY="your_db_name";
{ echo "SET FOREIGN_KEY_CHECKS = 0;" ; \
mysql "$DATABASE_TO_EMPTY" --skip-column-names -e \
"SELECT concat('DROP TABLE IF EXISTS ', table_name, ';') \
FROM information_schema.tables WHERE table_schema = '$DATABASE_TO_EMPTY';";\
} | mysql "$DATABASE_TO_EMPTY"
这将生成命令,然后立即将它们通过管道传输到将删除表的第二个客户端实例。
聪明的一点当然是从这里的其他答案中复制而来的——我只是想要一个可复制粘贴的单行(ish)来实际完成OP 想要的工作。
当然请注意,除非您的安全设置非常低,否则您也必须在这些 mysql 命令中(两次)输入您的凭据。(或者您可以为您的 mysql 命令别名以包含您的凭据。)
只需将Jonathan Watt的一些有用评论放在这里即可删除所有表格
MYSQL="mysql -h HOST -u USERNAME -pPASSWORD DB_NAME"
$MYSQL -BNe "show tables" | awk '{print "set foreign_key_checks=0; drop table `" $1 "`;"}' | $MYSQL
unset MYSQL
它对我有帮助,我希望它有用
在@Dion Truter 和@Wade Williams 的回答的基础上,以下shell 脚本将删除所有表,首先显示它将运行什么,并让您有机会使用Ctrl-C 中止。
#!/bin/bash
DB_HOST=xxx
DB_USERNAME=xxx
DB_PASSWORD=xxx
DB_NAME=xxx
CMD="mysql -sN -h ${DB_HOST} -u ${DB_USERNAME} -p${DB_PASSWORD} ${DB_NAME}"
# Generate the drop statements
TMPFILE=/tmp/drop-${RANDOM}.sql
echo 'SET FOREIGN_KEY_CHECKS = 0;' > ${TMPFILE}
${CMD} $@ >> ${TMPFILE} << ENDD
SELECT concat('DROP TABLE IF EXISTS \`', table_name, '\`;')
FROM information_schema.tables
WHERE table_schema = '${DB_NAME}';
ENDD
echo 'SET FOREIGN_KEY_CHECKS = 1;' >> ${TMPFILE}
# Warn what we are about to do
echo
cat ${TMPFILE}
echo
echo "Press ENTER to proceed (or Ctrl-C to abort)."
read
# Run the SQL
echo "Dropping tables..."
${CMD} $@ < ${TMPFILE}
echo "Exit status is ${?}."
rm ${TMPFILE}
这是一篇相当老的帖子,但在我看来,这里的答案都没有真正回答这个问题,所以我希望我的帖子能对人们有所帮助!
我在另一个对我来说非常有用的问题上找到了这个解决方案:
mysql -Nse 'show tables' DB_NAME | while read table; do mysql -e "SET FOREIGN_KEY_CHECKS=0; truncate table \`$table\`" DB_NAME; done
这实际上会清空数据库中的所有表DB_NAME
,而不仅仅是显示TRUNCATE
命令行。
希望这可以帮助!
只是一个温柔的提醒,
如果可能并且没有其他问题,您可以删除数据库并重新创建它。
- 删除数据库 <database_name>
- 创建数据库 <database_name>
简单明了(可能)。
可能不是一个花哨的解决方案,但这对我有用并挽救了我的一天。
适用于服务器版本:5.6.38 MySQL Community Server (GPL)
我遵循的步骤:
1. generate drop query using concat and group_concat.
2. use database
3. disable key constraint check
4. copy the query generated from step 1
5. enable key constraint check
6. run show table
MySQL 外壳
mysql> SYSTEM CLEAR;
mysql> SELECT CONCAT('DROP TABLE IF EXISTS `', GROUP_CONCAT(table_name SEPARATOR '`, `'), '`;') AS dropquery FROM information_schema.tables WHERE table_schema = 'emall_duplicate';
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| dropquery |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| DROP TABLE IF EXISTS `admin`, `app`, `app_meta_settings`, `commission`, `commission_history`, `coupon`, `email_templates`, `infopages`, `invoice`, `m_pc_xref`, `member`, `merchant`, `message_templates`, `mnotification`, `mshipping_address`, `notification`, `order`, `orderdetail`, `pattributes`, `pbrand`, `pcategory`, `permissions`, `pfeatures`, `pimage`, `preport`, `product`, `product_review`, `pspecification`, `ptechnical_specification`, `pwishlist`, `role_perms`, `roles`, `settings`, `test`, `testanother`, `user_perms`, `user_roles`, `users`, `wishlist`; |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> USE emall_duplicate;
Database changed
mysql> SET FOREIGN_KEY_CHECKS = 0; Query OK, 0 rows affected (0.00 sec)
// copy and paste generated query from step 1
mysql> DROP TABLE IF EXISTS `admin`, `app`, `app_meta_settings`, `commission`, `commission_history`, `coupon`, `email_templates`, `infopages`, `invoice`, `m_pc_xref`, `member`, `merchant`, `message_templates`, `mnotification`, `mshipping_address`, `notification`, `order`, `orderdetail`, `pattributes`, `pbrand`, `pcategory`, `permissions`, `pfeatures`, `pimage`, `preport`, `product`, `product_review`, `pspecification`, `ptechnical_specification`, `pwishlist`, `role_perms`, `roles`, `settings`, `test`, `testanother`, `user_perms`, `user_roles`, `users`, `wishlist`;
Query OK, 0 rows affected (0.18 sec)
mysql> SET FOREIGN_KEY_CHECKS = 1;
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW tables;
Empty set (0.01 sec)
mysql>
DB="your database name" \
&& mysql $DB < "SET FOREIGN_KEY_CHECKS=0" \
&& mysqldump --add-drop-table --no-data $DB | grep 'DROP TABLE' | grep -Ev "^$" | mysql $DB \
&& mysql $DB < "SET FOREIGN_KEY_CHECKS=1"
所有人都给出了很好的答案,但是,对于熟悉电子表格/Excel 工作表的用户,我有一个替代选择。根据第一个解决方案,我们得到一个命令列表,但我们仍然需要截断第一个和最后一个字符('|')
使用“
show tables;
”查询,您将获得所有表的列表;现在复制结果并将其粘贴到 Excel 表中(假设所有记录都在 excel 的“A”列中)
首先你需要删除第一个和最后一个'|' 删除第一个字符的符号函数,即。'|'
=右(A1,LEN(A1)-1)
删除最后一个字符的功能,即。'|' 并添加一个结束分号
=CONCAT(LEFT(B1,LEN(B1)-1),";")
现在使用 CONCAT 函数创建最终查询列表
=CONCAT("删除表",C1)
该解决方案基于@SkyLeach 答案,但支持使用外键删除表。
echo "SET FOREIGN_KEY_CHECKS = 0;" > ./drop_all_tables.sql
mysqldump --add-drop-table --no-data -u user -p dbname | grep 'DROP TABLE' >> ./drop_all_tables.sql
echo "SET FOREIGN_KEY_CHECKS = 1;" >> ./drop_all_tables.sql
mysql -u user -p dbname < ./drop_all_tables.sql
我将以下内容与 MSSQL 服务器一起使用:
if (DB_NAME() = 'YOUR_DATABASE')
begin
while(exists(select 1 from INFORMATION_SCHEMA.TABLE_CONSTRAINTS where CONSTRAINT_TYPE='FOREIGN KEY'))
begin
declare @sql nvarchar(2000)
SELECT TOP 1 @sql=('ALTER TABLE ' + TABLE_SCHEMA + '.[' + TABLE_NAME + '] DROP CONSTRAINT [' + CONSTRAINT_NAME + ']')
FROM information_schema.table_constraints
WHERE CONSTRAINT_TYPE = 'FOREIGN KEY'
exec (@sql)
PRINT @sql
end
while(exists(select 1 from INFORMATION_SCHEMA.TABLES))
begin
declare @sql2 nvarchar(2000)
SELECT TOP 1 @sql2=('DROP TABLE ' + TABLE_SCHEMA + '.[' + TABLE_NAME + ']')
FROM INFORMATION_SCHEMA.TABLES
exec (@sql2)
PRINT @sql2
end
end
else
print('Only run this script on the development server!!!!')
将 YOUR_DATABASE 替换为您的数据库名称或删除整个 IF 语句(我喜欢增加的安全性)。
迄今为止对我来说最好的解决方案
选择数据库 -> 右键单击 -> 任务 -> 生成脚本- 将打开生成脚本的向导。在 set Scripting 选项中选择对象后,单击Advanced Button。在“Script DROP and CREATE”下选择Script DROP。
运行脚本。