2

概括

我需要从超过 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

我错过了什么吗?

4

3 回答 3

4

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

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

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

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

无论如何,在有限大小的批次中运行删除是个好主意,因此它不会创建太多锁或向撤消段添加太多。

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

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

DELETE
    FROM SYS_VERROUS_POLICE
    WHERE dateHeureModification < (curdate() - INTERVAL 14 DAY)
    LIMIT 1000;
于 2017-11-13T17:36:08.337 回答
3

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

delete
    from SYS_VERROUS_POLICE
    where date(dateHeureModification)
                           <(curdate() - interval 14 day);
于 2017-11-13T17:03:51.897 回答
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
         );
于 2017-11-13T17:19:33.607 回答