摘要
我需要从超过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
我错过了什么吗?
答案 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
);