当前位置: 首页> 最新文章列表> 如何利用 PDOStatement 根据条件安全删除数据库中的记录?看完就会用

如何利用 PDOStatement 根据条件安全删除数据库中的记录?看完就会用

M66 2025-06-22

一、为什么使用 PDO 和预处理语句

在构造 SQL 删除语句时,很多开发者容易直接拼接字符串,比如这样:

$id = $_GET['id'];
$sql = "DELETE FROM users WHERE id = $id";

这种方式极易受到 SQL 注入攻击。例如,恶意用户传入 1 OR 1=1,就会删除整张表的内容。

使用 PDO 的预处理语句,则可以彻底避免这个问题。它通过将 SQL 和数据分离的方式,确保传入的数据不会被解释为 SQL 语句的一部分。


二、使用 PDO 删除记录的基本示例

下面是一个使用 PDO 删除用户记录的安全方式:

<?php
$dsn = 'mysql:host=localhost;dbname=testdb;charset=utf8mb4';
$username = 'root';
$password = 'your_password';

try {
    $pdo = new PDO($dsn, $username, $password);
    // 设置错误模式为异常
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // 预处理语句
    $stmt = $pdo->prepare("DELETE FROM users WHERE id = :id");

    // 绑定参数并执行
    $id = 5; // 例如从表单或 URL 获取的用户ID
    $stmt->bindParam(':id', $id, PDO::PARAM_INT);

    $stmt->execute();

    if ($stmt->rowCount()) {
        echo "记录已成功删除。";
    } else {
        echo "未找到匹配的记录。";
    }
} catch (PDOException $e) {
    echo "数据库错误: " . $e->getMessage();
}
?>

在这个例子中,我们使用了 :id 占位符,并通过 bindParam 绑定变量,确保数据类型一致性。


三、基于多个条件删除记录

有时删除条件不止一个,例如删除某个用户在特定时间的登录记录:

<?php
$stmt = $pdo->prepare("DELETE FROM login_logs WHERE user_id = :user_id AND login_time < :before_time");

$user_id = 3;
$before_time = '2024-01-01 00:00:00';

$stmt->bindParam(':user_id', $user_id, PDO::PARAM_INT);
$stmt->bindParam(':before_time', $before_time);

$stmt->execute();

四、动态条件的处理方式

如果删除条件是动态生成的,比如来自前端的复选框批量删除,可以这样构造:

<?php
$ids = [2, 5, 7]; // 来自表单或前端的 ID 列表

// 构造带有占位符的 SQL
$placeholders = implode(',', array_fill(0, count($ids), '?'));
$sql = "DELETE FROM users WHERE id IN ($placeholders)";
$stmt = $pdo->prepare($sql);

// 执行语句,绑定所有参数
$stmt->execute($ids);

这种方式利用了 ? 占位符和 execute 传入数组的能力,既安全又灵活。


五、安全建议

  1. 永远不要将用户输入直接拼接进 SQL 中。

  2. 使用绑定参数时,指定数据类型(如 PDO::PARAM_INT)可提高安全性与性能。

  3. 在删除之前可以先进行 SELECT 检查,确认操作对象是否存在。

  4. 使用事务处理(beginTransaction() / commit())以避免意外删除。


六、结合接口删除记录(RESTful 接口示例)

如果你想基于 HTTP 请求删除某条记录,例如通过接口 https://m66.net/api/delete_user.php?id=9,你可以这样写:

<?php
if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['id'])) {
    $id = (int) $_GET['id'];

    $stmt = $pdo->prepare("DELETE FROM users WHERE id = :id");
    $stmt->bindParam(':id', $id, PDO::PARAM_INT);
    $stmt->execute();

    echo json_encode([
        'success' => true,
        'message' => '用户删除成功',
    ]);
} else {
    http_response_code(400);
    echo json_encode([
        'success' => false,
        'message' => '请求不合法',
    ]);
}
?>

接口设计中同样必须重视输入验证和参数绑定,防止通过 API 的方式被攻击。