达到第50条记录时删除所有记录-sql / php

时间:2019-04-05 15:45:24

标签: php mysql sql

我详细解释了我的问题,我的数据库中有一个表,其中包含许多记录,每次在我的代码中,我都正确实现了已删除数据的备份功能。但是我的查询有问题。我举了一个简单的例子让人们理解。

例如,我的表中有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();
}
?>

3 个答案:

答案 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