SQL 维护脚本

Posted

技术标签:

【中文标题】SQL 维护脚本【英文标题】:SQL Maintenance Script 【发布时间】:2011-03-25 17:24:55 【问题描述】:

我有一张表格,表格如下

GROUP_ID | FOO | BAR | DATETIME

我有一个每天晚上更新这个表的 cron。但是我想,在我的脚本结束时运行一个 sql 命令,这将确保每个 group_id 的 50 个最新行都存在,并且其他任何行都被删除。

例如:如果有 60 行 GROUP_ID = 1,我希望在运行后只剩下 50 个最近的行。如果只有 20 行 GROUP_ID = 2,则将它们全部保留。

这是否可能仅在 SQL 中实现,或者我需要在 php 中执行此操作(我的大多数应用程序都是用它构建的)

我正在运行 mysql

谢谢

【问题讨论】:

【参考方案1】:

试穿一下尺寸:

DELIMITER $$
DECLARE groupCursor CURSOR FOR
SELECT GROUP_ID FROM mytable WHERE 
(SELECT COUNT(*) FROM mytable WHERE GROUP_ID=GROUP_ID) > 50;

DECLARE CONTINUE HANDLER FOR NOT FOUND done = 1;

DECLARE groupID INT;

read_loop: LOOP
FETCH groupCursor INTO groupID;
IF done THEN
   LEAVE read_loop;
ELSE
   DELETE FROM mytable
   WHERE GROUP_ID = groupID
   AND DATETIME < (SELECT MIN(DATETIME) FROM mytable WHERE GROUP_ID=groupID 
   ORDER BY DATETIME DESC LIMIT 50)
END IF;
END LOOP;
CLOSE groupCursor$$
DELIMITER ;

更新根据下面的讨论,这里是一个存储过程 CREATE 脚本,它应该是无语法错误的。

-- --------------------------------------------------------------------------------
-- Routine DDL
-- --------------------------------------------------------------------------------
DELIMITER $$

CREATE PROCEDURE `mydb`.`maintenanceTaskDelete` ()
BEGIN

DECLARE groupCursor CURSOR FOR SELECT GROUP_ID FROM mytable;
DECLARE done BIT DEFAULT 0;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

DECLARE groupID INT;

read_loop: LOOP
FETCH groupCursor INTO groupID;
IF done THEN
   LEAVE read_loop;
ELSE
   DELETE FROM mytable
   WHERE GROUP_ID = groupID
   AND DATETIME < (SELECT MIN(DATETIME) FROM mytable WHERE GROUP_ID=groupID 
   ORDER BY DATETIME DESC LIMIT 50);
END IF;
END LOOP;
CLOSE groupCursor;

END$$

要调用例程,您需要做的就是: CALL maintenanceTaskDelete();

【讨论】:

这是比我做过的更高级的 SQL,我有点理解发生了什么,尽管当我把它扔到 MySQL Workbench 中时,所有的 DECLARE 都被突出显示为红色,它会抛出一个错误。在第一行 我刚刚在响应中更新了我的脚本。如果您仍然遇到语法错误,请告诉我。 版本:5.0.77,第一次声明还是报错 您可能需要将上述所有代码放入一个存储过程(MySQL Workbench 中的“例程”)并调用该例程。 即使在例程中它说第一个声明是语法错误【参考方案2】:

尝试:

delete from yourtable 
where PK in (select pk 
             from (select 
                       pk, 
                       row_number() over(partition by GROUP_ID order by GROUP_ID, activity_date) as RowNumber
                   from yourtable
                   ) dt
             where RowNumber>50
            )

编辑 我刚刚看到这是针对 mysql 而不是 ms sql。 mysql没有row_number()。

【讨论】:

row_number() 未在 MySQL 中定义...如果我没记错那是 MS_SQL @,Alex Angelini,如果可以的话,我会删除这个答案。我不确定我在想什么,MySql 多次出现在这个问题中。

以上是关于SQL 维护脚本的主要内容,如果未能解决你的问题,请参考以下文章

Oracle DBA日常维护SQL脚本

史上最全近百条Oracle DBA日常维护SQL脚本指令

应用数据库维护工具

sqlserver脚本备份固定多个数据库

使用SQL Server维护计划实现数据库定时自动备份

sql server 如何执行一项计划任务