我正在尝试执行一个查询,删除过滤器表中不存在的images表中的所有文件。我正在跳过数据库中的3,500个最新文件,以便将表格“修剪”回过滤表中的3,500 +“X”条记录。
过滤器表包含文件的标记,以及images表中使用的文件ID。
代码将在cron作业上运行。
我的代码:
$sql = mysql_query("SELECT * FROM `images` ORDER BY `id` DESC") or die(mysql_error());
while($row = mysql_fetch_array($sql)){
$id = $row['id'];
$file = $row['url'];
$getId = mysql_query("SELECT `id` FROM `filter` WHERE `img_id` = '".$id."'") or die(mysql_error());
if(mysql_num_rows($getId) == 0){
$IdQue[] = $id;
$FileQue[] = $file;
}
}
for($i=3500; $i<$x; $i++){
mysql_query("DELETE FROM `images` WHERE id='".$IdQue[$i]."' LIMIT 1") or die("line 18".mysql_error());
unlink($FileQue[$i]) or die("file Not deleted");
}
echo ($i-3500)." files deleted.";
输出:删除了0个文件。
数据库内容:
images table: 10,000 rows
filters table: 63 rows
过滤器表中包含图像表ID的行数:63 php脚本的执行时间:4秒+/- 0.5秒
相关数据库结构
等...
表:过滤器
答案 0 :(得分:1)
for($i=3500; $i<$x; $i++){
如果$x < 3500
,则无效。你可能想要:
for($i=3500; $i<($x + 3500); $i++){
重新阅读有关SQL JOIN
的文档也是一个好主意。
答案 1 :(得分:1)
根据布兰登的答案,你可以建立一个subquery。您的整个脚本看起来就像:
$query = mysql_query(
"DELETE FROM `images` WHERE `id` NOT IN (
SELECT `id` from `filter`
) ORDER BY `id` DESC LIMIT 3500,12340283492834
") or die(mysql_error());
printf("Files deleted: %d\n", mysql_affected_rows());
子查询(SELECT `id` from `filter` LIMIT 3500,12340283492834)
首先解析并返回父查询的id列表,以便在WHERE
子句中使用。然后通过传入一个偏移来保留最后3500行(因此它会跳过前3500行,然后删除其余的行)。请注意丑陋的LIMIT 3500,12340283492834
...这是因为MySQL不支持无限制的偏移。
完成后,运行一个选择查询以获取所有图像 - 网址,然后循环浏览文件系统上的图像,如果文件名不在结果数组中,则将其删除。