在MySQL中删除超过14天的行

时间:2017-11-13 16:55:45

标签: mysql delete-row safe-mode

  

摘要

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

没有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
            );
  

抛出异常

但后来我坚持这个错误信息:

错误代码:1093。您无法在FROM子句中为更新指定目标表'SYS_VERROUS_POLICE'。

什么......

  

上下文

MySQL似乎在安全模式下运行,因此我将无法在匹配日期的情况下执行DELETE。

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

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

我错过了什么吗?

3 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:1)

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

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

您可以在删除查询中使用LIMIT使其满足安全更新模式。如果您使用LIMIT,MySQL会将其视为足以防止意外删除表中的所有行。

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

最好在有限大小的批次中运行删除,因此它不会创建太多的锁或为撤消段添加太多。

只需继续循环DELETE,一次删除1000行批次,并在每批后检查行受影响。当受影响的行达到0时停止循环。

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

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

答案 2 :(得分:0)

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

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

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
         );