我有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
不确定我做错了什么。 提前谢谢。
答案 0 :(得分:0)
你应该不评论-- SELECT @delStmt;
,并评论最后三行。
您将获得实际生成的SQL语句。
然后,您可以在实际服务器上复制并运行该语句以获取真正的错误消息。
我在自己的系统上运行了你的语句,我得到了null。
但是,我的系统上没有相同的表格,因此我删除了delStmt
中的where条件并获得以下内容:
DELETE FROM
information_schema
。ALL_PLUGINS
时间&lt; DATE(NOW() - 间隔2个月); DELETE FROMinformation_schema
。APPLICABLE_ROLES
时间&lt;日期(现在() - 间隔2个月);从information_schema
删除。CHARACTER_SETS
时间&lt;日期(现在() - 间隔2个月);删除information_schema
。COLLATIONS
时间&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();
答案 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;
感谢您的帮助