我详细解释了我的问题,我的数据库中有一个表,其中包含许多记录,每次在我的代码中,我都正确实现了已删除数据的备份功能。但是我的查询有问题。我举了一个简单的例子让人们理解。
例如,我的表中有100条记录,数字1是记录时间最长的记录,数字100是记录时间最短的记录。我想统计50条记录,并从51条记录中删除100条,以便删除并备份50条最旧的记录,并保留50条较年轻的记录,从而形成了连续的删除和备份周期。
一个愚蠢的例子,不会发生,只是使人们理解: 如果我有30条记录,请至少删除50、50个或更多,然后删除50
我30岁,请勿删除任何不超过50
我有51个,最老的delete1,我又有50个。
我有60个,从最早的10个删除,我又有50个。
我在下面为想要进行测试,创建文件夹和备份文件并正确记录每个删除字段的人员提供的代码,但是它并不能满足我的要求,但是每次脚本执行时启动,最终擦除数据库中的所有记录
<?php
//Start the session
session_start();
//Include connection
include 'connessione.php';
//Query to get stuff from database
$query_string = "SELECT * FROM utenti ORDER BY id ASC LIMIT 1 ";
$query = mysqli_query($connessione, $query_string);
//Get results
$results = mysqli_fetch_all($query, MYSQLI_ASSOC);
//Make that into a JSON array
$results = json_encode( $results );
function makeDirectory($path, $mode)
{
$return = mkdir($path, $mode, true);
return $return === true || is_dir($path);
}
$path = 'backup_LOG';
$mode = 0777;
$risultato = makeDirectory($path, $mode);
//Put those results in a file (create if file not exist)
$fileName = 'backup_LOG/backup_file_' . time() . '.txt';
$file = fopen( $fileName , 'a' );
fwrite( $file, $results );
fclose( $file );
//Delete the rows that you just backed up, but only if there are 50 or more.
if( sizeof( $results ) >= 1 )
{
$query_delete = "DELETE FROM utenti ORDER BY id DESC LIMIT 1";
mysqli_query( $connessione, $query_delete );
}
?>
最终代码
<?php
//Start the session
session_start();
//Include connection
include 'connessione.php';
$query = $connessione->query("
SELECT *
FROM utenti
ORDER BY id DESC
LIMIT 9999999999999999 -- just a very high number
OFFSET 1
");
$results = $query->fetch_all(MYSQLI_ASSOC);
$results = json_encode( $results );
if (count($results) > 0) {
// @todo backup the data
function makeDirectory($path, $mode)
{
$return = mkdir($path, $mode, true);
return $return === true || is_dir($path);
}
$path = 'backup_LOG';
$mode = 0777;
$risultato = makeDirectory($path, $mode);
$results = json_encode( $results );
//Put those results in a file (create if file not exist)
$fileName = 'backup_file_' . time() . '.txt';
$file = fopen( $fileName , 'a' );
fwrite( $file, $results );
fclose( $file );
// delete fetched rows
$firstId = reset($results)['id'];
$lastId = end($results)['id'];
$stmt = $connessione->prepare("DELETE FROM utenti WHERE id BETWEEN ? and ?");
$stmt->bind_param('ii', $firstId, $lastId);
$stmt->execute();
}
?>
答案 0 :(得分:0)
在MySQL 8中,您可以在子查询中使用窗口函数对记录进行排名和计数,然后将其与主表联接:
DELETE u
FROM utenti u
INNER JOIN (
SELECT
id,
ROW_NUMBER() OVER(ORDER BY id) rn,
COUNT(*) OVER() cnt
FROM utenti
) x ON u.id = x.id
WHERE x.cnt - 50 - x.rn >= 0
NB:由于大多数修改数据的操作,您都希望在数据库事务中运行它。
答案 1 :(得分:0)
您将需要用以下内容替换第一个查询:
SELECT *
FROM utenti
WHERE id < (SELECT MIN(id) FROM (SELECT id FROM utenti ORDER BY id DESC LIMIT 50))
ORDER BY id ASC;
在您的php中,在调用mysqli_fetch_all()和json_encode()之间,添加以下行:
$maxDeleteID = $results[count($results)-1]['id'];
更改您的删除查询以使用此新的php变量:
"DELETE FROM utenti WHERE id <= ". $maxDeleteID;
这应拉取最新记录之前的所有记录50,然后确保删除该备份中没有的所有内容。可以将记录添加到选择和删除之间的表中,因此您需要保存选择中的最大ID,并使用它来确保您不删除任何未备份的内容。
答案 2 :(得分:0)
使用OFFSET 50
跳过50个“垃圾”行。然后从提取的数据中使用第一个id
和最后一个$query = $connessione->query("
SELECT *
FROM utenti
ORDER BY id DESC
LIMIT 9999999999999999 -- just a very high number
OFFSET 50
");
$results = $query->fetch_all(MYSQLI_ASSOC);
if (count($results) > 0) {
// @todo backup the data
// delete fetched rows
$firstId = reset($results)['id'];
$lastId = end($results)['id'];
$stmt = $connessione->prepare("DELETE FROM utenti WHERE id BETWEEN ? and ?");
$stmt->bind_param('ii', $firstId, $lastId);
$stmt->execute();
}
删除它们之间的行。
LIMIT 9999999999999999
注意:OFFSET
是一种解决方法。我们不要LIMIT。但是在MySQL中,如果没有LIMIT
,就无法使用SELECT *
FROM utenti
WHERE id <= (
SELECT id
FROM utenti
ORDER BY id DESC
LIMIT 1
OFFSET 50
)
。如果您不输入“魔术”数字,也可以改用以下查询:
payload