从原始_%

时间:2017-11-06 10:35:02

标签: mysql prepared-statement

我有mysql数据库,其中包含来自其他系统的日志表。每个系统都有自己的表,我想自动删除超过2个月的日志。我几乎得到了它,但在准备声明期间我收到了一个错误。

这就是我得到的:

-- Set up variable to delete ALL tables starting with 'raw_'
SET GROUP_CONCAT_MAX_LEN=100000;

SET @delStmt = (SELECT GROUP_CONCAT(CONCAT('DELETE FROM `', TABLE_SCHEMA, '`.`', TABLE_NAME, '` WHERE time < DATE(NOW() - INTERVAL 2 MONTH);') SEPARATOR ' ')
       FROM information_schema.TABLES
      WHERE TABLE_SCHEMA = 'log_cmd'
        AND TABLE_NAME LIKE 'raw_%');

-- SELECT @delStmt;

PREPARE stmt FROM @delStmt;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

我得到的错误是:

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'DELETE FROM `log_cmd`.`raw_10203040` WHERE time < DATE(NOW() - INTERVAL 2 MONTH)' at line 1

不确定我做错了什么。 提前谢谢。

2 个答案:

答案 0 :(得分:0)

如何调试

你应该不评论-- SELECT @delStmt;,并评论最后三行。 您将获得实际生成的SQL语句。

然后,您可以在实际服务器上复制并运行该语句以获取真正的错误消息。

观察

我在自己的系统上运行了你的语句,我得到了null。

但是,我的系统上没有相同的表格,因此我删除了delStmt中的where条件并获得以下内容:

  

DELETE FROM information_schemaALL_PLUGINS时间&lt; DATE(NOW()    - 间隔2个月); DELETE FROM information_schemaAPPLICABLE_ROLES时间&lt;日期(现在() -   间隔2个月);从information_schema删除。CHARACTER_SETS   时间&lt;日期(现在() - 间隔2个月);删除   information_schemaCOLLATIONS时间&lt;日期(现在() - 间隔2   月); ...

列表继续......

更新

我认为该错误实际上与尝试执行两个SQL语句有关,由;分隔。

我能够逐个成功执行删除语句。

概念证明:

drop table raw_1;
create table raw_1(
  time int
);

drop table raw_2;
create table raw_2(
  time int
);

SET GROUP_CONCAT_MAX_LEN=100000;

SET @delStmt = (SELECT GROUP_CONCAT(CONCAT('DELETE FROM `', TABLE_SCHEMA, '`.`', TABLE_NAME, '` WHERE time < DATE(NOW() - INTERVAL 2 MONTH);') SEPARATOR ' ')
                FROM information_schema.TABLES
                WHERE TABLE_NAME LIKE 'raw_%');

SELECT @delStmt;

PREPARE stmt FROM @delStmt;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

结果:

DELETE FROM `test`.`raw_1` WHERE time < DATE(NOW() - INTERVAL 2 MONTH); \
DELETE FROM `test`.`raw_2` WHERE time < DATE(NOW() - INTERVAL 2 MONTH);

最终答案

由于是多个语句,命令失败了。将执行拆分为多个解决了问题。另一种解决方案是将命令保存到文件并执行(正如Alek所说)。

#Will not work without the following command/Setting:
SET SESSION sql_mode = CONCAT(@@sql_mode, ',PIPES_AS_CONCAT');

drop table raw_1;
create table  IF NOT EXISTS  raw_1(
  time int
);

create table  IF NOT EXISTS  raw_2(
  time int
);

SET SESSION sql_mode = CONCAT(@@sql_mode, ',PIPES_AS_CONCAT');

DROP PROCEDURE IF EXISTS `deleteFromLogs`;

CREATE PROCEDURE deleteFromLogs()
  BEGIN

    DECLARE torun varchar(100);
    DECLARE v_last_row_fetched INT;
    DECLARE counter CURSOR FOR SELECT 'DELETE FROM `' || TABLE_SCHEMA || '`.`' || TABLE_NAME || '` WHERE time < DATE(NOW() - INTERVAL 2 MONTH);' as torun
                               FROM information_schema.TABLES WHERE TABLE_NAME LIKE 'raw_%' AND TABLE_SCHEMA = 'log_cmd' ;

    DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_last_row_fetched = 1;

    SET SESSION sql_mode = CONCAT(@@sql_mode, ',PIPES_AS_CONCAT');

    OPEN counter;
    c1_loop: LOOP
      FETCH counter
      INTO torun;

      IF v_last_row_fetched = 1
      THEN LEAVE c1_loop;
      END IF;

      SET @delStmt = torun;
      select @delStmt;

#       PREPARE stmt1 FROM @delStmt;
#       EXECUTE stmt1;
#       DEALLOCATE PREPARE stmt1;
#       COMMIT;

    END LOOP c1_loop;
    CLOSE counter;

  END;


CALL deleteFromLogs();

https://www.db-fiddle.com/f/cVJ4uDhQYQALMvSURSEq4Y/1

答案 1 :(得分:0)

我找到了问题的解决方案。最简单的方法是将命令放入文件并执行它。

SET GROUP_CONCAT_MAX_LEN=100000;

SET @delStmt = (SELECT GROUP_CONCAT(CONCAT('DELETE FROM `', TABLE_SCHEMA, '`.`', TABLE_NAME, '` WHERE time < DATE(NOW() - INTERVAL 2 MONTH);') SEPARATOR ' ')
   FROM information_schema.TABLES
  WHERE TABLE_SCHEMA = 'log_cmd'
    AND TABLE_NAME LIKE 'raw_%');

SELECT @delStmt INTO OUTFILE '/tmp/temp.sql';
SOURCE /tmp/temp.sql;

感谢您的帮助