删除 MySQL 中超过 14 天的行

Delete rows older than 14 days in MySQL

Summary

我需要从超过 14 天的行中清除 table 的历史记录。

不是 MySQL 专家,我的搜索将我带到了这里:

delete
    from SYS_VERROUS_POLICE
    where idModificationPolice not in (
                select distinct idModificationPolice
                    from SYS_VERROUS_POLICE
                    where date(dateHeureModification) 
                            between curdate() and curdate() - interval 14 day
            );

Thrown Exception

但后来我遇到了这个错误消息:

错误代码:1093。您不能在 FROM 子句中为更新指定目标 table 'SYS_VERROUS_POLICE'。

什么...

Context

MySQL 似乎在安全模式下运行,所以我无法在匹配日期的地方执行删除。

在安全模式下,如果我尝试仅使用日期字段进行删除,则不符合要求。

delete  
  from SYS_VERROUS_POLICE     
 where date(dateHeureModification) < curdate() - interval 14 day    

Error Code: 1175. You are using safe update mode and you tried to update a table without a 
WHERE that uses a KEY column
To disable safe mode, toggle the option in Preferences -> SQL Editor and reconnect. 
0,00071 sec

我是不是漏掉了什么?

我不明白你为什么把它复杂化:

delete
    from SYS_VERROUS_POLICE
    where date(dateHeureModification)
                           <(curdate() - interval 14 day);

@Jean Dous 是正确答案。但只是为了解释您的查询中的问题是什么。您尝试检查与您正在更新的 table 相同的条件,这就像创建一个循环引用。

相反,您将 table 实现为子查询,以便您可以使用它。

delete
from SYS_VERROUS_POLICE
where idModificationPolice not in (
              select distinct T.idModificationPolice
              from (SELECT *
                    FROM SYS_VERROUS_POLICE) as T
              where date(T.dateHeureModification) 
                    between curdate() and curdate() - interval 14 day
         );

我理解您关于使用安全模式的观点。如果您尝试对非索引表达式使用 UPDATE 或 DELETE,它会抱怨,因为它无法估计您是否会意外删除整个 table.

DATE(dateHeureModification) > ... 上使用表达式 自然是未索引的。 MySQL 无法对函数的结果进行索引查找。

您可以在删除查询中使用 LIMIT 使其满足安全更新模式。如果您使用 LIMIT.

,MySQL 将其视为防止意外删除 table 中所有行的充分保护
DELETE
    FROM SYS_VERROUS_POLICE
    WHERE DATE(dateHeureModification) < (curdate() - INTERVAL 14 DAY)
    LIMIT 1000;

无论如何,运行 以有限的批次删除是个好主意,这样它就不会创建太多锁或向撤消段添加太多锁。

只需继续循环执行 DELETE,一次删除 1000 行的批次,并在每批之后检查 rows-affected。当 rows-affected 达到 0 时停止循环。

另一个想法:我认为您真的不需要在 WHERE 子句中使用 DATE() 函数。所以你可以像下面那样执行 DELETE,并且它可以使用索引。此外,如果您在 dateHeureModification 上有索引,查询检查任何行应该会更快。

DELETE
    FROM SYS_VERROUS_POLICE
    WHERE dateHeureModification < (curdate() - INTERVAL 14 DAY)
    LIMIT 1000;