我有一个包含以下表的数据库: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中实现它
答案 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 ;