🎬 HoRain 云小助手个人主页

⛺️生活的理想,就是为了理想的生活!


⛳️ 推荐

前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!忍不住分享一下给大家。点击跳转到网站。

目录

⛳️ 推荐

🗑️ PHP MySQL DELETE 操作完全指南

📋 目录

📝 DELETE 语句基础语法

基本 DELETE 语法

带 LIMIT 的 DELETE

多表删除(高级)

🔧 使用 MySQLi 执行 DELETE

1. 面向过程风格

2. 面向对象风格

🛡️ 使用 PDO 执行 DELETE

1. 基本 PDO 删除操作

2. 高级 PDO 删除操作

⚠️ WHERE 子句的重要性

1. 没有 WHERE 子句的危险

2. 安全的 WHERE 子句示例

🛡️ 安全注意事项与防SQL注入

1. SQL注入风险示例

2. 防止SQL注入的正确方法

3. 输入验证函数

🔍 错误处理与调试

1. 全面的错误处理

2. 调试和日志记录

📊 DELETE vs TRUNCATE vs DROP

比较表格

使用示例

🏗️ 实际应用示例

1. 完整的用户管理系统删除功能

2. 电子商务系统删除功能


🗑️ PHP MySQL DELETE 操作完全指南

在PHP中执行MySQL的DELETE操作是数据库管理的基础技能。DELETE语句用于从数据库表中删除记录,但需要谨慎使用,因为删除的数据通常无法恢复。

📋 目录

  1. DELETE 语句基础语法

  2. 使用 MySQLi 执行 DELETE

  3. 使用 PDO 执行 DELETE

  4. WHERE 子句的重要性

  5. 安全注意事项与防SQL注入

  6. 错误处理与调试

  7. DELETE vs TRUNCATE vs DROP

  8. 实际应用示例

  9. 最佳实践

📝 DELETE 语句基础语法

基本 DELETE 语法

-- 删除特定记录
DELETE FROM table_name WHERE condition;

-- 删除所有记录(危险!)
DELETE FROM table_name;

带 LIMIT 的 DELETE

-- 删除前N条匹配的记录
DELETE FROM table_name WHERE condition LIMIT 10;

-- 按排序删除
DELETE FROM table_name WHERE condition ORDER BY column_name LIMIT 5;

多表删除(高级)

-- 删除关联表中的记录
DELETE t1, t2 
FROM table1 t1 
INNER JOIN table2 t2 ON t1.id = t2.table1_id 
WHERE t1.status = 'inactive';

🔧 使用 MySQLi 执行 DELETE

1. 面向过程风格

<?php
// 数据库连接配置
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "my_database";

// 创建连接
$conn = mysqli_connect($servername, $username, $password, $dbname);

// 检查连接
if (!$conn) {
    die("连接失败: " . mysqli_connect_error());
}

// 示例1:删除特定记录(不安全 - 仅用于演示)
$id = 5;
$sql = "DELETE FROM users WHERE id = $id";

if (mysqli_query($conn, $sql)) {
    echo "记录删除成功";
} else {
    echo "错误: " . mysqli_error($conn);
}

// 示例2:使用预处理语句(安全)
$id = 5;
$sql = "DELETE FROM users WHERE id = ?";
$stmt = mysqli_prepare($conn, $sql);

if ($stmt) {
    // 绑定参数
    mysqli_stmt_bind_param($stmt, "i", $id);
    
    // 执行语句
    if (mysqli_stmt_execute($stmt)) {
        $affected_rows = mysqli_stmt_affected_rows($stmt);
        if ($affected_rows > 0) {
            echo "成功删除 {$affected_rows} 条记录";
        } else {
            echo "没有记录被删除(可能ID不存在)";
        }
    } else {
        echo "执行错误: " . mysqli_stmt_error($stmt);
    }
    
    // 关闭语句
    mysqli_stmt_close($stmt);
} else {
    echo "预处理错误: " . mysqli_error($conn);
}

// 关闭连接
mysqli_close($conn);
?>

2. 面向对象风格

<?php
// 数据库连接配置
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "my_database";

// 创建连接
$conn = new mysqli($servername, $username, $password, $dbname);

// 检查连接
if ($conn->connect_error) {
    die("连接失败: " . $conn->connect_error);
}

// 示例1:简单删除
$sql = "DELETE FROM products WHERE stock = 0";
if ($conn->query($sql) === TRUE) {
    echo "删除成功,影响行数: " . $conn->affected_rows;
} else {
    echo "错误: " . $conn->error;
}

// 示例2:使用预处理语句删除多条记录
$ids = [10, 15, 20];
$placeholders = implode(',', array_fill(0, count($ids), '?'));

$sql = "DELETE FROM orders WHERE id IN ($placeholders)";
$stmt = $conn->prepare($sql);

if ($stmt) {
    // 构建类型字符串
    $types = str_repeat('i', count($ids));
    
    // 绑定参数
    $stmt->bind_param($types, ...$ids);
    
    // 执行
    if ($stmt->execute()) {
        echo "成功删除 {$stmt->affected_rows} 条订单记录";
    } else {
        echo "删除失败: " . $stmt->error;
    }
    
    $stmt->close();
} else {
    echo "预处理失败: " . $conn->error;
}

// 示例3:带事务的删除
$conn->begin_transaction();

try {
    // 删除用户
    $user_id = 100;
    $sql1 = "DELETE FROM users WHERE id = ?";
    $stmt1 = $conn->prepare($sql1);
    $stmt1->bind_param("i", $user_id);
    $stmt1->execute();
    
    // 删除用户的订单
    $sql2 = "DELETE FROM orders WHERE user_id = ?";
    $stmt2 = $conn->prepare($sql2);
    $stmt2->bind_param("i", $user_id);
    $stmt2->execute();
    
    // 删除用户的评论
    $sql3 = "DELETE FROM comments WHERE user_id = ?";
    $stmt3 = $conn->prepare($sql3);
    $stmt3->bind_param("i", $user_id);
    $stmt3->execute();
    
    // 提交事务
    $conn->commit();
    echo "用户及相关数据删除成功";
    
} catch (Exception $e) {
    // 回滚事务
    $conn->rollback();
    echo "删除失败,已回滚: " . $e->getMessage();
}

// 关闭连接
$conn->close();
?>

🛡️ 使用 PDO 执行 DELETE

1. 基本 PDO 删除操作

<?php
// 数据库连接配置
$host = 'localhost';
$dbname = 'my_database';
$username = 'root';
$password = '';

try {
    // 创建PDO连接
    $pdo = new PDO(
        "mysql:host=$host;dbname=$dbname;charset=utf8mb4",
        $username,
        $password,
        [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::ATTR_EMULATE_PREPARES => false
        ]
    );
    
    // 示例1:删除单条记录
    $id = 25;
    $sql = "DELETE FROM products WHERE id = :id";
    $stmt = $pdo->prepare($sql);
    $stmt->execute([':id' => $id]);
    
    $rowCount = $stmt->rowCount();
    if ($rowCount > 0) {
        echo "成功删除 {$rowCount} 条产品记录";
    } else {
        echo "没有找到要删除的产品";
    }
    
    // 示例2:删除多条记录
    $category = 'electronics';
    $max_price = 100;
    
    $sql = "DELETE FROM products WHERE category = :category AND price > :price";
    $stmt = $pdo->prepare($sql);
    $stmt->execute([
        ':category' => $category,
        ':price' => $max_price
    ]);
    
    echo "删除高价电子产品: {$stmt->rowCount()} 条";
    
    // 示例3:使用IN子句删除多条记录
    $ids = [1, 3, 5, 7, 9];
    $placeholders = implode(',', array_fill(0, count($ids), '?'));
    
    $sql = "DELETE FROM users WHERE id IN ($placeholders)";
    $stmt = $pdo->prepare($sql);
    $stmt->execute($ids);
    
    echo "批量删除用户: {$stmt->rowCount()} 条";
    
} catch (PDOException $e) {
    die("数据库错误: " . $e->getMessage());
}
?>

2. 高级 PDO 删除操作

<?php
// 创建PDO连接(同上)

try {
    // 示例1:带LIMIT的删除
    $sql = "DELETE FROM log_entries WHERE created_at < DATE_SUB(NOW(), INTERVAL 30 DAY) LIMIT 1000";
    $stmt = $pdo->prepare($sql);
    $stmt->execute();
    
    echo "删除30天前的日志记录: {$stmt->rowCount()} 条";
    
    // 示例2:使用事务删除关联数据
    $pdo->beginTransaction();
    
    $user_id = 50;
    
    // 删除用户的所有订单
    $sql1 = "DELETE FROM orders WHERE user_id = ?";
    $stmt1 = $pdo->prepare($sql1);
    $stmt1->execute([$user_id]);
    $orders_deleted = $stmt1->rowCount();
    
    // 删除用户的所有评论
    $sql2 = "DELETE FROM comments WHERE user_id = ?";
    $stmt2 = $pdo->prepare($sql2);
    $stmt2->execute([$user_id]);
    $comments_deleted = $stmt2->rowCount();
    
    // 删除用户
    $sql3 = "DELETE FROM users WHERE id = ?";
    $stmt3 = $pdo->prepare($sql3);
    $stmt3->execute([$user_id]);
    $user_deleted = $stmt3->rowCount();
    
    // 提交事务
    $pdo->commit();
    
    echo "删除用户 {$user_id}: 删除{$orders_deleted}个订单, {$comments_deleted}条评论";
    
    // 示例3:使用命名参数的复杂删除
    $conditions = [
        'status' => 'inactive',
        'last_login' => '2023-01-01',
        'email_verified' => false
    ];
    
    $sql = "DELETE FROM users WHERE status = :status AND last_login < :last_login AND email_verified = :email_verified";
    $stmt = $pdo->prepare($sql);
    $stmt->execute($conditions);
    
    echo "删除不活跃用户: {$stmt->rowCount()} 条";
    
} catch (PDOException $e) {
    // 回滚事务
    if (isset($pdo) && $pdo->inTransaction()) {
        $pdo->rollBack();
    }
    die("操作失败: " . $e->getMessage());
}
?>

⚠️ WHERE 子句的重要性

1. 没有 WHERE 子句的危险

<?php
// ⚠️ 危险操作:删除所有数据!
$sql = "DELETE FROM users";  // 这将删除users表中的所有记录!

// 安全做法:总是使用WHERE子句
$sql = "DELETE FROM users WHERE id = 5";  // 只删除ID为5的记录

// 更好的做法:添加额外的安全限制
$sql = "DELETE FROM users WHERE id = 5 AND status = 'inactive'";
?>

2. 安全的 WHERE 子句示例

<?php
// 示例1:基于多个条件删除
$conditions = [
    'status' => 'deleted',
    'deleted_at' => '2022-01-01'
];

$sql = "DELETE FROM posts WHERE status = :status AND deleted_at < :deleted_at";

// 示例2:使用BETWEEN删除某个时间范围内的记录
$start_date = '2023-01-01';
$end_date = '2023-12-31';

$sql = "DELETE FROM logs WHERE created_at BETWEEN :start_date AND :end_date";

// 示例3:使用子查询删除
$sql = "DELETE FROM products 
        WHERE id IN (
            SELECT product_id 
            FROM order_items 
            GROUP BY product_id 
            HAVING COUNT(*) = 0
        )";

// 示例4:删除重复记录(保留一条)
$sql = "DELETE t1 FROM products t1
        INNER JOIN products t2 
        WHERE t1.id > t2.id 
        AND t1.sku = t2.sku";
?>

🛡️ 安全注意事项与防SQL注入

1. SQL注入风险示例

<?php
// ⚠️ 危险:直接拼接用户输入
$id = $_GET['id'];  // 用户输入:1 OR 1=1
$sql = "DELETE FROM users WHERE id = $id";
// 实际执行的SQL: DELETE FROM users WHERE id = 1 OR 1=1
// 结果:删除所有用户!

// ⚠️ 危险:使用addslashes也不安全
$id = addslashes($_GET['id']);  // 用户输入:1' OR '1'='1
$sql = "DELETE FROM users WHERE id = '$id'";
// 实际执行的SQL: DELETE FROM users WHERE id = '1' OR '1'='1'
// 结果:删除所有用户!
?>

2. 防止SQL注入的正确方法

<?php
// 方法1:使用预处理语句(MySQLi)
$id = $_GET['id'];
$sql = "DELETE FROM users WHERE id = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("i", $id);  // "i"表示整数类型
$stmt->execute();

// 方法2:使用预处理语句(PDO)
$id = $_GET['id'];
$sql = "DELETE FROM users WHERE id = :id";
$stmt = $pdo->prepare($sql);
$stmt->execute([':id' => $id]);

// 方法3:验证和过滤输入
function deleteUser($user_id) {
    // 验证输入是否为整数
    if (!filter_var($user_id, FILTER_VALIDATE_INT)) {
        throw new Exception("无效的用户ID");
    }
    
    // 验证ID范围
    if ($user_id <= 0) {
        throw new Exception("用户ID必须大于0");
    }
    
    // 使用预处理语句
    $sql = "DELETE FROM users WHERE id = ?";
    $stmt = $conn->prepare($sql);
    $stmt->bind_param("i", $user_id);
    $stmt->execute();
    
    return $stmt->affected_rows;
}

// 方法4:使用白名单验证
function deleteByStatus($status) {
    // 定义允许的状态值
    $allowed_statuses = ['inactive', 'banned', 'spam'];
    
    // 验证输入
    if (!in_array($status, $allowed_statuses)) {
        throw new Exception("不允许的状态值");
    }
    
    // 使用预处理语句
    $sql = "DELETE FROM users WHERE status = ?";
    $stmt = $conn->prepare($sql);
    $stmt->bind_param("s", $status);
    $stmt->execute();
    
    return $stmt->affected_rows;
}
?>

3. 输入验证函数

<?php
/**
 * 安全删除函数
 */
class SafeDeleter {
    private $conn;
    
    public function __construct($connection) {
        $this->conn = $connection;
    }
    
    /**
     * 安全删除单条记录
     */
    public function deleteById($table, $id, $id_column = 'id') {
        // 验证表名(防止SQL注入)
        if (!preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*$/', $table)) {
            throw new Exception("无效的表名");
        }
        
        // 验证列名
        if (!preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*$/', $id_column)) {
            throw new Exception("无效的列名");
        }
        
        // 验证ID
        if (!filter_var($id, FILTER_VALIDATE_INT) || $id <= 0) {
            throw new Exception("无效的ID");
        }
        
        // 使用预处理语句
        $sql = "DELETE FROM `$table` WHERE `$id_column` = ?";
        $stmt = $this->conn->prepare($sql);
        
        if (!$stmt) {
            throw new Exception("预处理失败: " . $this->conn->error);
        }
        
        $stmt->bind_param("i", $id);
        $stmt->execute();
        
        return $stmt->affected_rows;
    }
    
    /**
     * 批量安全删除
     */
    public function deleteMultiple($table, $ids, $id_column = 'id') {
        // 验证输入
        if (!is_array($ids) || empty($ids)) {
            throw new Exception("ID数组不能为空");
        }
        
        // 过滤和验证所有ID
        $valid_ids = [];
        foreach ($ids as $id) {
            if (filter_var($id, FILTER_VALIDATE_INT) && $id > 0) {
                $valid_ids[] = (int)$id;
            }
        }
        
        if (empty($valid_ids)) {
            return 0;
        }
        
        // 创建占位符
        $placeholders = implode(',', array_fill(0, count($valid_ids), '?'));
        
        // 使用预处理语句
        $sql = "DELETE FROM `$table` WHERE `$id_column` IN ($placeholders)";
        $stmt = $this->conn->prepare($sql);
        
        if (!$stmt) {
            throw new Exception("预处理失败: " . $this->conn->error);
        }
        
        // 构建类型字符串并绑定参数
        $types = str_repeat('i', count($valid_ids));
        $stmt->bind_param($types, ...$valid_ids);
        $stmt->execute();
        
        return $stmt->affected_rows;
    }
    
    /**
     * 带条件的删除
     */
    public function deleteWithConditions($table, $conditions) {
        // 验证表名
        if (!preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*$/', $table)) {
            throw new Exception("无效的表名");
        }
        
        // 构建WHERE子句
        $where_clauses = [];
        $params = [];
        $types = '';
        
        foreach ($conditions as $column => $value) {
            // 验证列名
            if (!preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*$/', $column)) {
                throw new Exception("无效的列名: $column");
            }
            
            $where_clauses[] = "`$column` = ?";
            
            // 确定参数类型
            if (is_int($value)) {
                $types .= 'i';
            } elseif (is_float($value)) {
                $types .= 'd';
            } else {
                $types .= 's';
            }
            
            $params[] = $value;
        }
        
        if (empty($where_clauses)) {
            throw new Exception("必须提供至少一个条件");
        }
        
        $where_sql = implode(' AND ', $where_clauses);
        $sql = "DELETE FROM `$table` WHERE $where_sql";
        
        $stmt = $this->conn->prepare($sql);
        if (!$stmt) {
            throw new Exception("预处理失败: " . $this->conn->error);
        }
        
        $stmt->bind_param($types, ...$params);
        $stmt->execute();
        
        return $stmt->affected_rows;
    }
}

// 使用示例
$deleter = new SafeDeleter($conn);

try {
    // 删除单条记录
    $deleted = $deleter->deleteById('users', 5);
    echo "删除 {$deleted} 条记录";
    
    // 批量删除
    $ids = [10, 15, 20];
    $deleted = $deleter->deleteMultiple('products', $ids);
    echo "批量删除 {$deleted} 条记录";
    
    // 带条件删除
    $conditions = [
        'status' => 'inactive',
        'last_login' => '2022-01-01'
    ];
    $deleted = $deleter->deleteWithConditions('users', $conditions);
    echo "条件删除 {$deleted} 条记录";
    
} catch (Exception $e) {
    echo "删除失败: " . $e->getMessage();
}
?>

🔍 错误处理与调试

1. 全面的错误处理

<?php
class DatabaseDeleter {
    private $conn;
    
    public function __construct($connection) {
        $this->conn = $connection;
    }
    
    /**
     * 安全删除记录
     */
    public function safeDelete($table, $id) {
        try {
            // 开启事务
            $this->conn->begin_transaction();
            
            // 1. 首先检查记录是否存在
            $check_sql = "SELECT COUNT(*) as count FROM `$table` WHERE id = ?";
            $check_stmt = $this->conn->prepare($check_sql);
            
            if (!$check_stmt) {
                throw new Exception("检查语句预处理失败: " . $this->conn->error);
            }
            
            $check_stmt->bind_param("i", $id);
            $check_stmt->execute();
            $check_stmt->bind_result($count);
            $check_stmt->fetch();
            $check_stmt->close();
            
            if ($count == 0) {
                throw new Exception("记录不存在,ID: $id");
            }
            
            // 2. 执行删除
            $delete_sql = "DELETE FROM `$table` WHERE id = ?";
            $delete_stmt = $this->conn->prepare($delete_sql);
            
            if (!$delete_stmt) {
                throw new Exception("删除语句预处理失败: " . $this->conn->error);
            }
            
            $delete_stmt->bind_param("i", $id);
            $delete_stmt->execute();
            
            $affected_rows = $delete_stmt->affected_rows;
            $delete_stmt->close();
            
            if ($affected_rows == 0) {
                throw new Exception("删除失败,可能记录已被删除");
            }
            
            // 3. 记录删除日志
            $this->logDeletion($table, $id, $affected_rows);
            
            // 提交事务
            $this->conn->commit();
            
            return [
                'success' => true,
                'affected_rows' => $affected_rows,
                'message' => "成功删除 {$affected_rows} 条记录"
            ];
            
        } catch (Exception $e) {
            // 回滚事务
            if ($this->conn->in_transaction) {
                $this->conn->rollback();
            }
            
            return [
                'success' => false,
                'error' => $e->getMessage(),
                'code' => $e->getCode()
            ];
        }
    }
    
    /**
     * 记录删除日志
     */
    private function logDeletion($table, $id, $affected_rows) {
        $log_sql = "INSERT INTO deletion_logs (table_name, record_id, affected_rows, deleted_at, deleted_by) 
                    VALUES (?, ?, ?, NOW(), ?)";
        
        $log_stmt = $this->conn->prepare($log_sql);
        
        // 获取当前用户(示例)
        $deleted_by = $_SESSION['user_id'] ?? 'system';
        
        $log_stmt->bind_param("siis", $table, $id, $affected_rows, $deleted_by);
        $log_stmt->execute();
        $log_stmt->close();
    }
    
    /**
     * 软删除(标记删除而非物理删除)
     */
    public function softDelete($table, $id) {
        try {
            $sql = "UPDATE `$table` SET 
                    is_deleted = 1,
                    deleted_at = NOW(),
                    deleted_by = ?
                    WHERE id = ? AND is_deleted = 0";
            
            $stmt = $this->conn->prepare($sql);
            
            if (!$stmt) {
                throw new Exception("预处理失败: " . $this->conn->error);
            }
            
            $deleted_by = $_SESSION['user_id'] ?? 'system';
            $stmt->bind_param("si", $deleted_by, $id);
            $stmt->execute();
            
            $affected_rows = $stmt->affected_rows;
            $stmt->close();
            
            if ($affected_rows == 0) {
                throw new Exception("记录不存在或已被删除");
            }
            
            return [
                'success' => true,
                'affected_rows' => $affected_rows,
                'message' => "成功标记删除 {$affected_rows} 条记录"
            ];
            
        } catch (Exception $e) {
            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }
}

// 使用示例
$deleter = new DatabaseDeleter($conn);

// 硬删除
$result = $deleter->safeDelete('users', 5);
if ($result['success']) {
    echo $result['message'];
} else {
    echo "删除失败: " . $result['error'];
}

// 软删除
$result = $deleter->softDelete('products', 10);
if ($result['success']) {
    echo $result['message'];
} else {
    echo "删除失败: " . $result['error'];
}
?>

2. 调试和日志记录

<?php
class DebugDeleter {
    private $conn;
    private $debug;
    
    public function __construct($connection, $debug = false) {
        $this->conn = $connection;
        $this->debug = $debug;
    }
    
    /**
     * 带调试的删除操作
     */
    public function deleteWithDebug($table, $conditions) {
        // 记录开始时间
        $start_time = microtime(true);
        
        try {
            // 构建SQL
            $where_parts = [];
            $params = [];
            $types = '';
            
            foreach ($conditions as $key => $value) {
                $where_parts[] = "`$key` = ?";
                $params[] = $value;
                
                if (is_int($value)) {
                    $types .= 'i';
                } elseif (is_float($value)) {
                    $types .= 'd';
                } else {
                    $types .= 's';
                }
            }
            
            $where_sql = implode(' AND ', $where_parts);
            $sql = "DELETE FROM `$table` WHERE $where_sql";
            
            // 调试信息
            if ($this->debug) {
                $this->logDebug("SQL: $sql");
                $this->logDebug("参数: " . print_r($params, true));
                $this->logDebug("类型: $types");
            }
            
            // 准备语句
            $stmt = $this->conn->prepare($sql);
            if (!$stmt) {
                $error = $this->conn->error;
                $this->logError("预处理失败: $error");
                throw new Exception("预处理失败: $error");
            }
            
            // 绑定参数
            if (!empty($params)) {
                $stmt->bind_param($types, ...$params);
            }
            
            // 执行
            $executed = $stmt->execute();
            
            if (!$executed) {
                $error = $stmt->error;
                $this->logError("执行失败: $error");
                throw new Exception("执行失败: $error");
            }
            
            $affected_rows = $stmt->affected_rows;
            $stmt->close();
            
            // 记录执行时间
            $end_time = microtime(true);
            $execution_time = round(($end_time - $start_time) * 1000, 2);
            
            if ($this->debug) {
                $this->logDebug("影响行数: $affected_rows");
                $this->logDebug("执行时间: {$execution_time}ms");
            }
            
            return [
                'success' => true,
                'affected_rows' => $affected_rows,
                'execution_time' => $execution_time,
                'sql' => $sql
            ];
            
        } catch (Exception $e) {
            $end_time = microtime(true);
            $execution_time = round(($end_time - $start_time) * 1000, 2);
            
            $this->logError("删除失败: " . $e->getMessage());
            $this->logError("执行时间: {$execution_time}ms");
            
            return [
                'success' => false,
                'error' => $e->getMessage(),
                'execution_time' => $execution_time
            ];
        }
    }
    
    /**
     * 记录调试信息
     */
    private function logDebug($message) {
        $log = "[" . date('Y-m-d H:i:s') . "] DEBUG: $message\n";
        file_put_contents('debug.log', $log, FILE_APPEND);
        echo "<pre>DEBUG: $message</pre>";
    }
    
    /**
     * 记录错误信息
     */
    private function logError($message) {
        $log = "[" . date('Y-m-d H:i:s') . "] ERROR: $message\n";
        file_put_contents('error.log', $log, FILE_APPEND);
        echo "<pre style='color: red;'>ERROR: $message</pre>";
    }
}

// 使用示例
$debugDeleter = new DebugDeleter($conn, true);

$conditions = [
    'status' => 'inactive',
    'created_at' => '2022-01-01'
];

$result = $debugDeleter->deleteWithDebug('users', $conditions);

if ($result['success']) {
    echo "删除成功,影响行数: " . $result['affected_rows'];
} else {
    echo "删除失败: " . $result['error'];
}
?>

📊 DELETE vs TRUNCATE vs DROP

比较表格

特性

DELETE

TRUNCATE

DROP

操作类型

DML(数据操作语言)

DDL(数据定义语言)

DDL(数据定义语言)

删除内容

删除表中的记录

删除表中的所有记录

删除整个表

WHERE子句

支持,可以条件删除

不支持,总是删除所有记录

不支持

事务

支持,可以回滚

不支持,不能回滚

不支持,不能回滚

触发器

会触发DELETE触发器

不会触发触发器

不会触发触发器

性能

较慢,逐行删除

很快,直接删除数据页

很快

自增ID

不重置自增计数器

重置自增计数器

删除表结构

日志

记录每行删除日志

记录页释放日志

记录表删除日志

恢复

可以通过事务回滚恢复

无法恢复

无法恢复

使用示例

<?php
// 1. DELETE - 删除特定记录(可恢复)
$sql = "DELETE FROM users WHERE status = 'inactive'";
// 特点:可以回滚,触发触发器,较慢

// 2. TRUNCATE - 快速清空表(不可恢复)
$sql = "TRUNCATE TABLE temp_data";
// 特点:不能回滚,不触发触发器,很快,重置自增ID

// 3. DROP - 删除整个表(不可恢复)
$sql = "DROP TABLE IF EXISTS old_table";
// 特点:删除表结构和所有数据

// 选择建议:
// - 需要条件删除时使用 DELETE
// - 需要快速清空整个表时使用 TRUNCATE
// - 需要删除整个表结构时使用 DROP
?>

🏗️ 实际应用示例

1. 完整的用户管理系统删除功能

<?php
class UserManager {
    private $conn;
    
    public function __construct($connection) {
        $this->conn = $connection;
    }
    
    /**
     * 删除用户(硬删除)
     */
    public function deleteUser($user_id, $permanent = false) {
        try {
            $this->conn->begin_transaction();
            
            // 验证用户是否存在
            $user = $this->getUserById($user_id);
            if (!$user) {
                throw new Exception("用户不存在");
            }
            
            if ($permanent) {
                // 永久删除
                $this->permanentDeleteUser($user_id);
            } else {
                // 软删除
                $this->softDeleteUser($user_id);
            }
            
            $this->conn->commit();
            return ['success' => true, 'message' => '用户删除成功'];
            
        } catch (Exception $e) {
            $this->conn->rollback();
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }
    
    /**
     * 永久删除用户及相关数据
     */
    private function permanentDeleteUser($user_id) {
        // 删除顺序:从外键约束最少的表开始
        $tables = [
            'user_sessions',    // 会话
            'user_logs',        // 日志
            'user_comments',    // 评论
            'user_orders',      // 订单
            'user_addresses',   // 地址
            'users'             // 用户
        ];
        
        foreach ($tables as $table) {
            $sql = "DELETE FROM $table WHERE user_id = ?";
            $stmt = $this->conn->prepare($sql);
            $stmt->bind_param("i", $user_id);
            $stmt->execute();
            $stmt->close();
        }
        
        $this->logAction('permanent_delete', $user_id, '永久删除用户');
    }
    
    /**
     * 软删除用户
     */
    private function softDeleteUser($user_id) {
        $sql = "UPDATE users SET 
                status = 'deleted',
                deleted_at = NOW(),
                deleted_by = ?
                WHERE id = ? AND status != 'deleted'";
        
        $deleted_by = $_SESSION['user_id'] ?? 'system';
        $stmt = $this->conn->prepare($sql);
        $stmt->bind_param("si", $deleted_by, $user_id);
        $stmt->execute();
        
        $affected = $stmt->affected_rows;
        $stmt->close();
        
        if ($affected > 0) {
            $this->logAction('soft_delete', $user_id, '软删除用户');
        }
    }
    
    /**
     * 批量删除不活跃用户
     */
    public function deleteInactiveUsers($days = 365) {
        try {
            $sql = "DELETE FROM users 
                    WHERE last_login < DATE_SUB(NOW(), INTERVAL ? DAY) 
                    AND status = 'active'";
            
            $stmt = $this->conn->prepare($sql);
            $stmt->bind_param("i", $days);
            $stmt->execute();
            
            $deleted_count = $stmt->affected_rows;
            $stmt->close();
            
            $this->logAction('batch_delete', null, "批量删除{$deleted_count}个不活跃用户");
            
            return [
                'success' => true,
                'deleted_count' => $deleted_count,
                'message' => "成功删除 {$deleted_count} 个不活跃用户"
            ];
            
        } catch (Exception $e) {
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }
    
    /**
     * 获取用户信息
     */
    private function getUserById($user_id) {
        $sql = "SELECT * FROM users WHERE id = ?";
        $stmt = $this->conn->prepare($sql);
        $stmt->bind_param("i", $user_id);
        $stmt->execute();
        
        $result = $stmt->get_result();
        $user = $result->fetch_assoc();
        
        $stmt->close();
        return $user;
    }
    
    /**
     * 记录操作日志
     */
    private function logAction($action, $target_id, $description) {
        $sql = "INSERT INTO audit_logs (action, target_id, description, performed_by, performed_at) 
                VALUES (?, ?, ?, ?, NOW())";
        
        $performed_by = $_SESSION['user_id'] ?? 'system';
        $stmt = $this->conn->prepare($sql);
        $stmt->bind_param("siss", $action, $target_id, $description, $performed_by);
        $stmt->execute();
        $stmt->close();
    }
}

// 使用示例
$userManager = new UserManager($conn);

// 删除单个用户(软删除)
$result = $userManager->deleteUser(5);
if ($result['success']) {
    echo $result['message'];
}

// 永久删除用户
$result = $userManager->deleteUser(10, true);
if ($result['success']) {
    echo $result['message'];
}

// 批量删除不活跃用户
$result = $userManager->deleteInactiveUsers(180); // 删除180天未登录的用户
if ($result['success']) {
    echo $result['message'];
}
?>

2. 电子商务系统删除功能

<?php
class ProductManager {
    private $conn;
    
    public function __construct($connection) {
        $this->conn = $connection;
    }
    
    /**
     * 删除产品(带库存检查)
     */
    public function deleteProduct($product_id) {
        try {
            $this->conn->begin_transaction();
            
            // 检查产品是否存在
            $product = $this->getProduct($product_id);
            if (!$product) {
                throw new Exception("产品不存在");
            }
            
            // 检查是否有未完成的订单
            if ($this->hasPendingOrders($product_id)) {
                throw new Exception("产品有未完成的订单,无法删除");
            }
            
            // 检查库存
            if ($product['stock'] > 0) {
                throw new Exception("产品还有库存,请先清空库存");
            }
            
            // 软删除产品
            $sql = "UPDATE products SET 
                    is_deleted = 1,
                    deleted_at = NOW(),
                    deleted_by = ?
                    WHERE id = ?";
            
            $deleted_by = $_SESSION['user_id'] ?? 'system';
            $stmt = $this->conn->prepare($sql);
            $stmt->bind_param("si", $deleted_by, $product_id);
            $stmt->execute();
            
            // 记录删除日志
            $this->logProductDeletion($product_id, $product['name']);
            
            $this->conn->commit();
            
            return [
                'success' => true,
                'message' => "产品 '{$product['name']}' 已删除"
            ];
            
        } catch (Exception $e) {
            $this->conn->rollback();
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }
    
    /**
     * 批量删除过期产品
     */
    public function deleteExpiredProducts() {
        try {
            $sql = "SELECT id, name FROM products 
                    WHERE expiry_date < NOW() 
                    AND is_deleted = 0";
            
            $stmt = $this->conn->prepare($sql);
            $stmt->execute();
            $result = $stmt->get_result();
            
            $deleted_products = [];
            $error_products = [];
            
            while ($product = $result->fetch_assoc()) {
                $delete_result = $this->deleteProduct($product['id']);
                
                if ($delete_result['success']) {
                    $deleted_products[] = $product['name'];
                } else {
                    $error_products[] = [
                        'name' => $product['name'],
                        'error' => $delete_result['error']
                    ];
                }
            }
            
            $stmt->close();
            
            return [
                'success' => true,
                'deleted' => $deleted_products,
                'errors' => $error_products,
                'message' => sprintf(
                    "成功删除 %d 个产品,%d 个失败",
                    count($deleted_products),
                    count($error_products)
                )
            ];
            
        } catch (Exception $e) {
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }
    
    /**
     * 删除产品分类(级联删除)
     */
    public function deleteCategory($category_id) {
        try {
            $this->conn->begin_transaction();
            
            // 检查分类是否存在
            $category = $this->getCategory($category_id);
            if (!$category) {
                throw new Exception("分类不存在");
            }
            
            // 检查分类下是否有产品
            if ($this->categoryHasProducts($category_id)) {
                throw new Exception("分类下有产品,无法删除");
            }
            
            // 删除分类
            $sql = "DELETE FROM categories WHERE id = ?";
            $stmt = $this->conn->prepare($sql);
            $stmt->bind_param("i", $category_id);
            $stmt->execute();
            
            $this->conn->commit();
            
            return [
                'success' => true,
                'message' => "分类 '{$category['name']}' 已删除"
            ];
            
        } catch (Exception $e) {
            $this->conn->rollback();
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }
    
    private function getProduct($product_id) {
        $sql = "SELECT * FROM products WHERE id = ?";
        $stmt = $this->conn->prepare($sql);
        $stmt->bind_param("i", $product_id);
        $stmt->execute();
        $result = $stmt->get_result();
        $product = $result->fetch_assoc();
        $stmt->close();
        return $product;
    }
    
    private function hasPendingOrders($product_id) {
        $sql = "SELECT COUNT(*) as count FROM order_items oi
                JOIN orders o ON oi.order_id = o.id
                WHERE oi.product_id = ? AND o.status IN ('pending', 'processing')";
        
        $stmt = $this->conn->prepare($sql);
        $stmt->bind_param("i", $product_id);
        $stmt->execute();
        $stmt->bind_result($count);
        $stmt->fetch();
        $stmt->close();
        
        return $count > 0;
    }
    
    private function logProductDeletion($product_id, $product_name) {
        $sql = "INSERT INTO product_deletion_log 
                (product_id, product_name, deleted_by, deleted_at) 
                VALUES (?, ?, ?, NOW())";
        
        $deleted_by = $_SESSION['user_id'] ?? 'system';
        $stmt = $this->conn->prepare($sql);
        $stmt->bind_param("iss", $product_id, $product_name, $deleted_by);
        $stmt->execute();
        $stmt->close();
    }
    
    private function getCategory($category_id) {
        $sql = "SELECT * FROM categories WHERE id = ?";
        $stmt = $this->conn->prepare($sql);
        $stmt->bind_param("i", $category_id);
        $stmt->execute();
        $result = $stmt->get_result();
        $category = $result->fetch_assoc();
        $stmt->close();
        return $category;
    }
    
    private function categoryHasProducts($category_id)

❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐