在一个命令中截断MySQL数据库中的所有表?

Truncate all tables in a MySQL database in one command?

是否有一个查询(命令)在一个操作中截断数据库中的所有表?我想知道我是否可以用一个查询来完成这项工作。


删除(即删除表格)

1
mysql -Nse 'show tables' DATABASE_NAME | while read table; do mysql -e"drop table $table" DATABASE_NAME; done

截断(即空表)

1
mysql -Nse 'show tables' DATABASE_NAME | while read table; do mysql -e"truncate table $table" DATABASE_NAME; done


在MySQL实例上截断多个数据库表

1
2
SELECT Concat('TRUNCATE TABLE ',table_schema,'.',TABLE_NAME, ';')
FROM INFORMATION_SCHEMA.TABLES where  table_schema in ('db1_name','db2_name');

使用查询结果截断表

注:可能你会得到这个错误:

1
ERROR 1217 (23000): Cannot delete or update a parent row: a foreign key constraint fails

如果有表具有对要删除/截断的表的外键引用,则会发生这种情况。

在截断表之前,您需要做的就是:

1
SET FOREIGN_KEY_CHECKS=0;

截断表并将其改回

1
SET FOREIGN_KEY_CHECKS=1;


以这种方式使用phpmyadmin:

Database View => Check All (tables) => Empty

如果要忽略外键检查,可以取消选中显示以下内容的框:

[ ] Enable foreign key checks

您需要至少运行4.5.0或更高版本才能获得此复选框。

它不是mysql的cli-fu,但是嘿,它工作了!


MS SQL Server 2005+(删除打印以实际执行…)

1
EXEC sp_MSforeachtable 'PRINT ''TRUNCATE TABLE ?'''

如果您的数据库平台支持信息模式视图,请获取以下查询的结果并执行它们。

1
SELECT 'TRUNCATE TABLE ' + TABLE_NAME FROM INFORMATION_SCHEMA.TABLES

为MySQL尝试此操作:

1
SELECT Concat('TRUNCATE TABLE ', TABLE_NAME) FROM INFORMATION_SCHEMA.TABLES

向concat中添加分号可以更容易地使用,例如,在mysql工作台中使用分号。

1
SELECT Concat('TRUNCATE TABLE ', TABLE_NAME, ';') FROM INFORMATION_SCHEMA.TABLES


我发现这是为了删除数据库中的所有表:

1
mysqldump -uUSERNAME -pPASSWORD --add-drop-table --no-data DATABASENAME | grep ^DROP | mysql -uUSERNAME -pPASSWORD DATABASENAME

如果您受到托管解决方案的限制(无法删除整个数据库),则非常有用。

我修改了它以截断表。mysqldump没有"--add truncate table",所以我这样做了:

1
mysqldump -uUSERNAME -pPASSWORD --add-drop-table --no-data DATABASENAME | grep ^DROP | sed -e 's/DROP TABLE IF EXISTS/TRUNCATE TABLE/g' | mysql -uUSERNAME -pPASSWORD DATABASENAME

为我工作--编辑,修复最后一个命令中的拼写错误


1
2
3
4
5
6
7
8
9
10
11
12
13
14
SET FOREIGN_KEY_CHECKS = 0;

SELECT @str := CONCAT('TRUNCATE TABLE ', table_schema, '.', table_name, ';')
FROM   information_schema.tables
WHERE  table_type   = 'BASE TABLE'
  AND  table_schema IN ('db1_name','db2_name');

PREPARE stmt FROM @str;

EXECUTE stmt;

DEALLOCATE PREPARE stmt;

SET FOREIGN_KEY_CHECKS = 1;

这将打印截断所有表的命令:

1
SELECT GROUP_CONCAT(Concat('TRUNCATE TABLE ',table_schema,'.',TABLE_NAME) SEPARATOR ';') FROM INFORMATION_SCHEMA.TABLES where table_schema in ('my_db');

我发现最简单的方法就是执行下面的代码,用自己的表名替换表名。重要事项确保最后一行始终设置外键检查=1;

1
2
3
4
5
6
7
8
9
SET FOREIGN_KEY_CHECKS=0;
TRUNCATE `table1`;
TRUNCATE `table2`;
TRUNCATE `table3`;
TRUNCATE `table4`;
TRUNCATE `table5`;
TRUNCATE `table6`;
TRUNCATE `table7`;
SET FOREIGN_KEY_CHECKS=1;


  • 要截断一个表,必须从其他表中删除映射到此表中的列的外键约束(实际上是在特定db/schema中的所有表上)。
  • 因此,必须首先删除所有外键约束,然后进行表截断。
  • 或者,在数据截断后,使用optimize表(在mysql、innodb engine esp中)将使用的数据空间/大小回收到OS。
  • 执行数据截断后,在同一个表上再次创建相同的外键约束。请参阅下面的脚本,该脚本将生成用于执行上述操作的脚本。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    SELECT CONCAT('ALTER TABLE ',TABLE_SCHEMA,'.',TABLE_NAME,' DROP FOREIGN KEY ',CONSTRAINT_NAME,';') FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
    WHERE CONSTRAINT_TYPE='FOREIGN KEY' AND TABLE_SCHEMA='<TABLE SCHEMA>'
    UNION
    SELECT CONCAT('TRUNCATE TABLE ',TABLE_SCHEMA,'.',TABLE_NAME,';') FROM INFORMATION_SCHEMA.TABLES
    WHERE TABLE_SCHEMA='<TABLE SCHEMA>' AND TABLE_TYPE='BASE TABLE'
    UNION
    SELECT CONCAT('OPTIMIZE TABLE ',TABLE_SCHEMA,'.',TABLE_NAME,';') FROM INFORMATION_SCHEMA.TABLES
    WHERE TABLE_SCHEMA='<TABLE SCHEMA>' AND TABLE_TYPE='BASE TABLE'
    UNION
    SELECT CONCAT('ALTER TABLE ',TABLE_SCHEMA,'.',TABLE_NAME,' ADD CONSTRAINT ',CONSTRAINT_NAME,' FOREIGN KEY(',COLUMN_NAME,')',' REFERENCES ',REFERENCED_TABLE_NAME,'(',REFERENCED_COLUMN_NAME,');') FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
    WHERE CONSTRAINT_NAME LIKE 'FK%' AND TABLE_SCHEMA='<TABLE SCHEMA>'
    INTO OUTFILE"C:/DB Truncate.sql" LINES TERMINATED BY '
    '
    ;
  • 现在,运行生成的db truncate.sql脚本

    好处。1)回收磁盘空间2)不需要删除和重新创建具有相同结构的数据库/架构

    缺点。1)fk约束应该是表中的名称,约束名称中包含"fk"。


    使用此项并形成查询

    1
    2
    3
    SELECT Concat('TRUNCATE TABLE ',table_schema,'.',TABLE_NAME, ';')
    FROM INFORMATION_SCHEMA.TABLES where  table_schema in (db1,db2)
    INTO OUTFILE '/path/to/file.sql';

    现在使用这个来使用这个查询

    1
    mysql -u username -p </path/to/file.sql

    如果你遇到这样的错误

    1
    ERROR 1701 (42000) at line 3: Cannot truncate a table referenced in a foreign key constraint

    最简单的方法是在文件的顶部添加此行

    1
    SET FOREIGN_KEY_CHECKS=0;

    也就是说,我们不想在浏览这个文件时检查外键约束。

    它将截断数据库db1和bd2中的所有表。


    如果使用SQL Server 2005,则有一个隐藏的存储过程,允许您对数据库中的所有表执行一个命令或一组命令。下面是使用此存储过程调用TRUNCATE TABLE的方法:

    1
    EXEC [sp_MSforeachtable] @command1="TRUNCATE TABLE ?"

    这是一篇很好的文章,详细阐述。

    但是,对于MySQL,可以使用mysqldump并指定--add-drop-tables--no-data选项来删除和创建忽略数据的所有表。这样地:

    1
    mysqldump -u[USERNAME] -p[PASSWORD] --add-drop-table --no-data [DATABASE]

    dev.mysql中的mysqldump使用指南


    不,没有一个命令可以同时截断所有mysql表。您必须创建一个小脚本来逐个截断表。

    参考:http://dev.mysql.com/doc/refman/5.0/en/truncate-table.html


    我知道我在这里

    1
    2
       SELECT Concat('TRUNCATE TABLE ',table_schema,'.',TABLE_NAME, ';')
        FROM INFORMATION_SCHEMA.TABLES where  table_schema in ('databasename1','databasename2');

    如果不能删除或更新的行:a parent key约束条fails

    那事如果有证明人与对外表两个表的钥匙,你是想滴/附加。

    截断表之前,所有你需要做的是:两个

    1
    SET FOREIGN_KEY_CHECKS=0;

    你的桌子和附加两个换回来

    1
    SET FOREIGN_KEY_CHECKS=1;

    PHP代码的用户。

    1
    2
    3
    4
    5
    6
    7
    8
        $truncate = mysql_query("SELECT Concat('TRUNCATE TABLE ',table_schema,'.',TABLE_NAME, ';') as tables_query FROM INFORMATION_SCHEMA.TABLES where table_schema in ('databasename')");

        while($truncateRow=mysql_fetch_assoc($truncate)){

            mysql_query($truncateRow['tables_query']);

        }
    ?>

    在这里检查的零售 链接


    这里是我的变体,它有"one语句来截断'em all'。

    首先,我正在为助手存储过程使用一个名为"util"的单独数据库。截断所有表的存储过程代码是:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    DROP PROCEDURE IF EXISTS trunctables;
    DELIMITER ;;
    CREATE  PROCEDURE trunctables(theDb varchar(64))
    BEGIN
        declare tname varchar(64);
        declare tcursor CURSOR FOR
        SELECT table_name FROM information_schema.tables WHERE table_type <> 'VIEW' AND table_schema = theDb;
        SET FOREIGN_KEY_CHECKS = 0;
        OPEN tcursor;
        l1: LOOP
            FETCH tcursor INTO tname;
            if tname = NULL then leave l1; end if;
            set @sql = CONCAT('truncate `', theDB, '`.`', tname, '`');
            PREPARE stmt from @sql;
            EXECUTE stmt;
            DEALLOCATE PREPARE stmt;
        END LOOP l1;
        CLOSE tcursor;
        SET FOREIGN_KEY_CHECKS = 1;
    END ;;
    DELIMITER ;

    一旦在UTIL数据库中有了这个存储过程,就可以像这样调用它

    1
    call util.trunctables('nameofdatabase');

    这正是一个声明:—)


    我发现那个截断表……使用外键约束有困难,即使在nocheck约束all之后,我还是使用delete from语句。这意味着标识种子不会重置,您可以始终添加一个DBCC CHECKIDENT来实现这一点。

    在运行SQL之前,我使用下面的代码将截断数据库中所有表的SQL输出到消息窗口。这只会让犯错误变得更加困难。

    1
    2
    3
    EXEC sp_MSforeachtable 'PRINT ''ALTER TABLE ? NOCHECK CONSTRAINT ALL'''
    EXEC sp_MSforeachtable 'print ''DELETE FROM ?'''
    EXEC sp_MSforeachtable 'print ''ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all'''

    下面是一个应该截断本地数据库中所有表的过程。

    如果不起作用,请通知我,我将删除此答案。

    未经测试的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    CREATE PROCEDURE truncate_all_tables()
    BEGIN

       -- Declare local variables
       DECLARE done BOOLEAN DEFAULT 0;
       DECLARE cmd VARCHAR(2000);

       -- Declare the cursor
       DECLARE cmds CURSOR
       FOR
       SELECT CONCAT('TRUNCATE TABLE ', TABLE_NAME) FROM INFORMATION_SCHEMA.TABLES;

       -- Declare continue handler
       DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;

       -- Open the cursor
       OPEN cmds;

       -- Loop through all rows
       REPEAT

          -- Get order number
          FETCH cmds INTO cmd;

          -- Execute the command
          PREPARE stmt FROM cmd;
          EXECUTE stmt;
          DROP PREPARE stmt;

       -- End of loop
       UNTIL done END REPEAT;

       -- Close the cursor
       CLOSE cmds;

    END;


    我不确定,但我认为有一个命令可以用来将数据库的模式复制到新的数据库中,一旦完成此操作,就可以删除旧的数据库,然后再将数据库模式复制到旧名称中。


    我知道这不是一个命令,但是通过以下步骤可以从phpmyadmin中获得所需的结果:

  • 选择(所有)要删除的表(全部选中)
  • 从"with selected:"列表中选择"drop"/"truncate"。
  • 在确认页上("您真的想:")复制查询(所有内容都有红色背景)
  • 在顶部单击SQL并写入:"set foreignu keyu checks=0";然后粘贴以前复制的查询
  • 点击"go"
  • 其思想是快速从数据库中获取所有表(您只需5秒钟和2次单击即可完成),但首先禁用外键检查。没有cli,也没有删除数据库并再次添加。


    1
    2
    3
    4
    5
    6
    TB=$( mysql -Bse"show tables from DATABASE" );
    for i in ${TB};
        do echo"Truncating table ${i}";
        mysql -e"set foreign_key_checks=0; set unique_checks=0;truncate table DATABASE.${i}; set foreign_key_checks=1; set unique_checks=1";
        sleep 1;
    done

    ——

    戴维

    感谢您花时间来格式化代码,但这是应用代码的方式。

    -库尔特

    在Unix或Linux设备上:

    确保你是在一个巴什壳。这些命令将从命令行运行,如下所示。

    注:

    我将我的凭证存储在~/.my.cnf文件中,因此不需要在命令行上提供它们。

    注:

    cpm是数据库名称

    我只显示每个命令的一小部分结果样本。

    查找外键约束:

    1
    2
    3
    4
    klarsen@Chaos:~$ mysql -Bse"select concat(table_name, ' depends on ', referenced_table_name)
                 from information_schema.referential_constraints
                 where constraint_schema = 'cpm'
                 order by referenced_table_name"
  • 批准外部系统取决于批准请求
  • 地址取决于客户
  • 客户识别取决于客户
  • 外部ID取决于客户
  • 凭证取决于客户
  • 电子邮件地址取决于客户
  • 批准请求取决于客户
  • 客户状态取决于客户
  • 客户形象取决于客户
  • 列出表和行计数:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    klarsen@Chaos:~$ mysql -Bse"SELECT table_name, table_rows FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'cpm'" | cat -n

     1  address 297
     2  approval_external_system    0
     3  approval_request    0
     4  country 189
     5  credential  468
     6  customer    6776
     7  customer_identification 5631
     8  customer_image  2
     9  customer_status 13639

    截断表:

    1
    klarsen@Chaos:~$ TB=$( mysql -Bse"show tables from cpm" ); for i in ${TB}; do echo"Truncating table ${i}"; mysql -e"set foreign_key_checks=0; set unique_checks=0;truncate table cpm.${i}; set foreign_key_checks=1; set unique_checks=1"; sleep 1; done
  • 截断表地址
  • 截断表审批外部系统
  • 截断表审批请求
  • 截断表国家/地区
  • 截断表凭据
  • 截断表客户
  • 截断表客户标识
  • 截断表客户图像
  • 截断表客户状态
  • 验证它是否有效:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    klarsen@Chaos:~$ mysql -Bse"SELECT table_name, table_rows FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'cpm'" | cat -n

     1  address 0
     2  approval_external_system    0
     3  approval_request    0
     4  country 0
     5  credential  0
     6  customer    0
     7  customer_identification 0
     8  customer_image  0
     9  customer_status 0
    10  email_address   0

    在Windows框中:

    注:

    cpm是数据库名称

    1
    C:\>for /F"tokens=*" %a IN ('mysql -Bse"show tables" cpm') do mysql -e"set foreign_key_checks=0; set unique_checks=0; truncate table %a; foreign_key_checks=1; set unique_checks=1" cpm


    下面的mysql查询本身将生成一个查询,该查询将截断给定数据库中的所有表。它绕过了外键:

    1
    2
    3
    4
    5
    6
    7
    8
    SELECT CONCAT(
             'SET FOREIGN_KEY_CHECKS=0; ',
             GROUP_CONCAT(dropTableSql SEPARATOR '; '), '; ',
             'SET FOREIGN_KEY_CHECKS=1;'
           ) as dropAllTablesSql
    FROM   ( SELECT  Concat('TRUNCATE TABLE ', table_schema, '.', TABLE_NAME) AS dropTableSql
             FROM    INFORMATION_SCHEMA.TABLES
             WHERE   table_schema = 'DATABASE_NAME' ) as queries

    1
    2
    3
    mysqldump -u root -p --no-data dbname > schema.sql
    mysqldump -u root -p drop dbname
    mysqldump -u root -p < schema.sql

    索恩1)

    1
    2
    mysql> select group_concat('truncate',' ',table_name,';') from information_schema.tables where table_schema="db_name" into outfile '/tmp/a.txt';
    mysql> /tmp/a.txt;

    索恩2)

    1
    2
    3
    - Export only structure of a db
    - drop the database
    - import the .sql of structure

    --编辑----

    1
    earlier in solution 1, i had mentioned concat() instead of group_concat() which would have not returned the desired result


    一个想法可能是直接删除并重新创建表?

    编辑:

    @乔纳森·莱弗勒:对

    其他建议(或不需要截断所有表的情况):

    为什么不创建一个基本的存储过程来截断特定的表呢?

    1
    2
    3
    4
    5
    6
    CREATE PROCEDURE [dbo].[proc_TruncateTables]
    AS
    TRUNCATE TABLE Table1
    TRUNCATE TABLE Table2
    TRUNCATE TABLE Table3
    GO


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <?php
    // connect to database
    $conn=mysqli_connect("localhost","user","password","database");

    // check connection
    if (mysqli_connect_errno()) {
      exit('Connect failed: '. mysqli_connect_error());
    }

    // sql query
    $sql =mysqli_query($conn,"TRUNCATE" . TABLE_NAME);


    // Print message
    if ($sql === TRUE) {
      echo 'data delete successfully';
    }
    else {
     echo 'Error: '. $conn->error;
    }

    $conn->close();

    ?>

    这是我用来清除表的代码段。只需更改$conn信息和表名。