截断MySQL数据库中与名称模式匹配的所有表

问题描述 投票:33回答:11

我需要清除所有库存表。

我试过这个:

SELECT 'TRUNCATE TABLE ' + TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'inventory%'

但我得到这个错误:

Truncated incorrect DOUBLE value: 'TRUNCATE TABLE ' Error Code 1292

如果这是正确的方法,那么我做错了什么?

sql mysql
11个回答
60
投票

使用concat:

SELECT concat('TRUNCATE TABLE `', TABLE_NAME, '`;')
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'inventory%'

这当然只会生成您需要自己复制和运行的SQL。


0
投票

迟到的答案......但后来要好,永远不要。为了避免不必要的复制和粘贴或额外的shell脚本,最不可知的方法 - 至少就MySQL和MariaDB而言 - 截断数据库中的一组表或匹配模式是通过存储过程。

以下是定期用于截断当前数据库中所有表的脚本。如果需要更精确的控制,可以定制SELECT语句以匹配模式。

DROP PROCEDURE IF EXISTS truncate_tables;

DELIMITER $$
CREATE PROCEDURE truncate_tables()
BEGIN
  DECLARE tblName CHAR(64);
  DECLARE done INT DEFAULT FALSE;
  DECLARE dbTables CURSOR FOR
    SELECT table_name
    FROM information_schema.tables
    WHERE table_schema = (SELECT DATABASE());
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  OPEN dbTables;
  SET FOREIGN_KEY_CHECKS = 0;

  read_loop: LOOP
    FETCH dbTables INTO tblName;
    IF done THEN
      LEAVE read_loop;
    END IF;

    PREPARE stmt FROM CONCAT('TRUNCATE ', tblName);
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
  END LOOP read_loop;

  CLOSE dbTables;
  SET FOREIGN_KEY_CHECKS = 1;
END
$$

CALL truncate_tables();
DROP PROCEDURE IF EXISTS truncate_tables;

此示例在使用后删除存储过程。但是,如果这是一个常规任务,那么最好通过在$$分隔符之前运行所有内容并执行它来添加一次

CALL truncate_tables();

在目标数据库上。


-1
投票

使用concat的非常好的示例生成和执行语句我刚刚读过:

http://www.mysqltutorial.org/mysql-drop-table

-- set table schema and pattern matching for tables

SET @schema = 'classicmodels';
SET @pattern = 'test%';

-- build dynamic sql (DROP TABLE tbl1, tbl2...;)

SELECT CONCAT('DROP TABLE ',GROUP_CONCAT(CONCAT(@schema,'.',table_name)),';')
INTO @droplike FROM information_schema.tables WHERE @schema = database()
AND table_name LIKE @pattern;

-- display the dynamic sql statement

SELECT @droplike;  

-- execute dynamic sql

PREPARE stmt FROM @dropcmd;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

7
投票

我知道它已经是一个较旧的帖子但是以下示例对于需要从linux命令行或从shell脚本中截断多个表的人有帮助:

mysql -p<secret> --execute="SELECT concat('TRUNCATE TABLE ', TABLE_NAME, ';') FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '<database>' AND FIND_IN_SET(TABLE_NAME,'your_table_a,your_table_b,your_table_c')" | sed 1d | mysql -p<secret> <database>

鉴于您需要用自己的值替换括号中的字符串,它对我有用。同时将'your_table_a,your_table_b,your_table_c'替换为以逗号分隔的表格列表。 ;)


6
投票
SELECT 'SET FOREIGN_KEY_CHECKS = 0;'
UNION
SELECT DISTINCT concat( "TRUNCATE TABLE ", TABLE_NAME, ";" )
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'mydbname'
UNION
SELECT 'SET FOREIGN_KEY_CHECKS = 1;'

4
投票

如果您使用命令行,您可能想尝试这样的事情。

mysql -u [user] -p[password] -e 'use [database]; show tables' | perl -lane 'print "truncate table $F[0]" if /^inventory/i' > [database].sql

2
投票

以上是对上述SQL语句的一点改进。

SELECT DISTINCT concat("TRUNCATE TABLE ", TABLE_NAME, ";") 
FROM INFORMATION_SCHEMA.TABLES 
WHERE TABLE_NAME LIKE "cache%"

请注意开头的DISTINCT命令。这将使SELECT结果仅显示与LIKE条件匹配的表。


1
投票

如果服务器上有多个数据库,则可能还需要指定数据库。

例如清除Drupal缓存表

SELECT DISTINCT CONCAT(  
    "TRUNCATE TABLE ", 
    TABLE_SCHEMA,  
    ".",
    TABLE_NAME, 
    ";" ) 
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE  "cache_%"
AND TABLE_SCHEMA = 'dbname';

这导致sql像......

TRUNCATE TABLE dbname.cache_admin_menu;
TRUNCATE TABLE dbname.cache_block;
etc.

给两个好处,

  1. 无论当前选择的数据库如何,您都可以在任何地方运行此sql。
  2. 您将确保在正确的数据库上截断表。

如果外键检查妨碍了你的质量截断,请参阅@falperez回答(当然它们不会用于drupal缓存清除)


1
投票

尝试这个语句,它将为您提供所有表的单行,您可以复制该语句并运行以执行所有:

SELECT DISTINCT REPLACE(GROUP_CONCAT("TRUNCATE TABLE ", TABLE_NAME, ";"), ',', '')
FROM INFORMATION_SCHEMA.TABLES 
WHERE TABLE_NAME LIKE "cache%";

0
投票
SELECT CONCAT('TRUNCATE TABLE ',TABLE_NAME)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'inventory%'

然后,您应该获取结果集的每一行并将其称为SQL语句。您可以通过将分离的结果复制并粘贴到命令窗口来完成。

但更好的解决方案是编写一些程序,使上面的查询循环并循环结果并进行每个查询。

将PHP用于该语言或任何其他脚本语言。很多例子甚至在这里也是如此。


0
投票
SELECT REPLACE(GROUP_CONCAT("TRUNCATE TABLE ", TABLE_NAME, ";"), ',', '') 
FROM INFORMATION_SCHEMA.TABLES 
WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME LIKE "cache%";

这是基于AshwinP的答案。我不得不删除DISTINCT并添加WHERE TABLE_SCHEMA = DATABASE()以便它为我工作。

该命令不截断表,但返回一个单行。将单行复制并粘贴到mysql客户端。

© www.soinside.com 2019 - 2024. All rights reserved.