临时表和行及其名称的事件计划程序

时间:2018-10-11 23:46:07

标签: mysql temp-tables mysql-event

我有一个包含以下表的数据库:temp_1,temp_2 ....和cached_tbl。在cached_tbl内部,我有列table_name,并在相应的行中存储了上面提到的所有临时表名。因此,我想做的是创建事件调度程序,该程序将删除一天以上创建的临时表...为此,我正在编写类似

的内容
SELECT (DROP) 
    *
FROM
    information_schema.TABLES
WHERE 
    table_schema = 'db' and CREATE_TIME < (NOW()-INTERVAL 24 HOUR)

但是我还想删除cached_tbl表中包含刚刚删除的表名的行...请告知我该怎么做...在常规编程中,我只需要将以前脚本中所有选定的table_names都放入数组中并循环比较此表名和cached_tbls中的表名...但是我不知道如何在mysql中实现它

2 个答案:

答案 0 :(得分:0)

嗨,欢迎来到SO。

回答您的问题-您不应该那样做(遍历临时表等)。一般来说,临时表仅用于您当前的连接(会话),当您关闭一个临时表时,所有临时表都将消失。这是正常的。临时表应该为您的逻辑提供某种额外的缓存-例如,当您需要将结果从一个过程导出到另一个过程时。

但是您需要记住,SQL用于数据的持久存储及其管理,如果要存储数据,请使用普通表,而MySQL将完成其余工作。使用触发器或存储过程来检查/刷新表中的数据。

更具体地讲临时表名称。检查手册-https://dev.mysql.com/doc/refman/5.7/en/innodb-information-schema-temp-table-info.html-您会看到MySQL自己存储了临时表的名称

CREATE TEMPORARY TABLE t1 (c1 INT PRIMARY KEY) ENGINE=INNODB;

SELECT * FROM INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO\G
*************************** 1. row ***************************
            TABLE_ID: 194
                NAME: #sql7a79_1_0
              N_COLS: 4
               SPACE: 182
PER_TABLE_TABLESPACE: FALSE
       IS_COMPRESSED: FALSE

这不是 t1 表,而是#sql7a79_1_0 。您可以说-等等,我知道表格的名称是 t1 ! -但您应该记住,t1只是您在当前会话中使用的一种指针,并且出于您自己的目的,MySQL依赖于其自身的机制。

答案 1 :(得分:0)

Alisa,我假设您正在使用命名约定temp_1,temp_2来表示您打算在短时间内删除这些表,并且这些不是@anton推测的TEMPORARY表。

在下面的示例中有几点要注意ab:

它被写为一个事件,但是您可以轻松地将其变成一个过程,该过程将允许您传递不同的间隔值或数据库名称。

您将需要使用游标来获取表名,并使用动态SQL来准备和执行语句以删除表并删除cached_tbl中的记录。

为了使您能够在一条语句中创建和填充TEMPORARY表,我将其复杂程度比严格必要的要复杂一些,如果您确实将其转换为过程,这将非常有用。您可以通过将游标声明为@ sql1中的语句并删除stmt1上的prepare和execute来简化它。

您可能希望在选择表时更加严格一些,否则可能会意外删除cached_tbl或其他数据库表。

DELIMITER //

CREATE EVENT prune
ON SCHEDULE
  EVERY 1 DAY
DO

  BEGIN
    DECLARE done BOOLEAN DEFAULT FALSE;
    DECLARE tname VARCHAR(64);
    DECLARE cur CURSOR FOR SELECT * FROM `tables_tmp`;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

    SET @sql1 = 
      'CREATE TEMPORARY TABLE `tables_tmp`  
       SELECT `table_schema`,`table_name`  
       FROM `information_schema`.`tables`
       WHERE `table_schema` = ''db''
       AND `table_name` LIKE ''temp_%'' 
       AND `create_time` < (NOW() - INTERVAL 1 DAY)';

    PREPARE stmt1 FROM @sql1;
    EXECUTE stmt1;
    DEALLOCATE PREPARE stmt1;

    OPEN cur;

    myloop:LOOP
      FETCH cur INTO tname;

      IF done = TRUE THEN
        LEAVE myloop;
      END IF;

      SET @sql2 = CONCAT('DROP TABLE IF EXISTS `db`.`', tname , '`;'); 
      PREPARE stmt2 FROM @sql2;
      EXECUTE stmt2;
      DEALLOCATE PREPARE stmt2;

      SET @sql3 = CONCAT('DELETE FROM `cached_tbl` WHERE `table_name` = ''', tname , ''';'); 
      PREPARE stmt3 FROM @sql3;
      EXECUTE stmt3;
      DEALLOCATE PREPARE stmt3;

    END LOOP;

  END //

DELIMITER ;