← PHP更新MySQL数据记录:从基础到实践 PHP查询MySQL数据:SELECT语句 →

PHP删除MySQL数据记录:DELETE语句

原创 2026-05-21 PHP 已有人查阅

老早之前PHP有个mysql_query()函数,能直接删数据。但这东西PHP 5.5开始就被标记为过时了,后续版本直接给踢出去了。你要是还在用这个,要么项目是十年前的祖传代码,要么就是刚入坑还不知道情况。

现在正经写PHP删除操作,就两条路:MySQLi和PDO。MySQLi分面向过程和面向对象两种写法,PDO更适合需要换数据库的项目。

DELETE语句长啥样

DELETE FROM 表名 WHERE 条件;

这里有个坑必须说清楚:不带WHERE就是把整个表清空。我见过有新手在正式环境跑了个DELETE FROM users,忘记加条件,那场面简直惨不忍睹。生产库没备份的话,收拾东西走人都是轻的。

MySQLi面向过程写法

这是最直接的写法,适合写小脚本或者快速测试用。

<?php
$host = 'localhost:3306';
$user = 'root';
$pass = '123456';
$dbname = 'company_db';

$conn = mysqli_connect($host, $user, $pass, $dbname);

if (!$conn) {
    die('连不上数据库:' . mysqli_connect_error());
}

// 删除id为5的员工
$id = 5;
$sql = "DELETE FROM employees WHERE id = $id";

if (mysqli_query($conn, $sql)) {
    echo "员工记录已删除";
} else {
    echo "删除失败:" . mysqli_error($conn);
}

mysqli_close($conn);
?>

动手之前看一眼数据:

id name department
1 张三 技术部
2 李四 市场部
3 王五
4 赵六 技术部
5 老钱 财务部

执行之后:

id name department
1 张三 技术部
2 李四 市场部
3 王五
4 赵六 技术部

id=5的那条没了。

个人经验: 这种直接把变量拼进SQL的做法,如果$id是从用户输入来的(比如GET参数),那SQL注入风险很高。上面只是演示,实际项目中别这么干,往下看预处理就明白了。

MySQLi面向对象写法

<?php
$mysqli = new mysqli("localhost", "root", "123456", "company_db");

if ($mysqli->connect_error) {
    die("连接失败:" . $mysqli->connect_error);
}

$sql = "DELETE FROM employees WHERE id = 3";

if ($mysqli->query($sql) === true) {
    echo "id为3的记录已删除";
} else {
    echo "删除出错:" . $mysqli->error;
}

$mysqli->close();
?>

处理前数据:

id name salary
1 张三 8000
2 李四 9500
3 王五 7000
4 赵六 11000

处理后数据:

id name salary
1 张三 8000
2 李四 9500
4 赵六 11000

说一下区别: 面向过程和面向对象本质上都是MySQLi扩展,只不过写法习惯不同。团队项目里面向对象更常见,因为和后面要说的PDO风格接近,切换成本低。

PDO方式删除

PDO的好处是换个数据库不用改太多代码,比如从MySQL切到PostgreSQL,连接字符串改一下就行。

<?php
try {
    $pdo = new PDO("mysql:host=localhost;dbname=company_db", "root", "123456");
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $sql = "DELETE FROM employees WHERE id = 2";
    $pdo->exec($sql);
    echo "删除成功";

} catch (PDOException $e) {
    die("执行失败:" . $e->getMessage());
}

unset($pdo);
?>

注意: exec()用来执行没有结果集返回的SQL,比如DELETE、UPDATE、INSERT。如果执行SELECT用exec会报错。

预处理语句(重点)

上面几个例子有个共同毛病:SQL里直接拼变量。这习惯必须改。

MySQLi预处理

<?php
$conn = new mysqli("localhost", "root", "123456", "company_db");

if ($conn->connect_error) {
    die("连不上:" . $conn->connect_error);
}

// 要删除的用户ID,这个值可以来自表单、URL参数等
$user_id = 7;

$stmt = $conn->prepare("DELETE FROM employees WHERE id = ?");
$stmt->bind_param("i", $user_id);  // i表示integer类型

if ($stmt->execute()) {
    echo "安全删除完成";
} else {
    echo "删除失败:" . $stmt->error;
}

$stmt->close();
$conn->close();
?>

bind_param的常见类型:

  • i - 整数

  • d - 浮点数

  • s - 字符串

  • b - 二进制数据(比如图片文件)

PDO预处理

<?php
try {
    $pdo = new PDO("mysql:host=localhost;dbname=company_db", "root", "123456");
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $stmt = $pdo->prepare("DELETE FROM employees WHERE id = :uid");
    $stmt->bindParam(':uid', $employee_id);

    $employee_id = 7;
    $stmt->execute();

    echo "PDO预处理删除成功";

} catch (PDOException $e) {
    echo "出错了:" . $e->getMessage();
}

$pdo = null;
?>

个人见解: 我个人更偏好PDO的命名参数写法(:uid这种),一眼就能看出每个参数对应什么,不像?占位符还得数位置。项目里有七八个参数的时候,数问号能数到眼花。

实际案例:按条件批量删除

案例一:按精确ID删除

表名叫users,数据如下:

id username email
1 alan alan@ebingou.cn
2 betty betty@xxx.com
3 carl carl@xxx.com
4 diana diana@xxx.com

删除id=3的记录:

DELETE FROM users WHERE id = 3

案例二:按条件批量删除

假设有个products表:

id product_name category price
1 机械键盘 外设 299
2 游戏鼠标 外设 159
3 4K显示器 外设 1899
4 C++入门 书籍 59
5 Python实战 书籍 79

删除所有category='书籍'的记录:

DELETE FROM products WHERE category = '书籍'

删除后:

id product_name category price
1 机械键盘 外设 299
2 游戏鼠标 外设 159
3 4K显示器 外设 1899

实际场景: 电商系统里下架某个分类的商品,或者论坛批量删除某个违规用户发的所有帖子,都是用WHERE条件批量处理。

本节课程知识要点

  1. 必须带WHERE条件 —— 不加条件等于TRUNCATE TABLE,数据直接没了

  2. 优先用预处理语句 —— 不是技术洁癖,是安全底线

  3. MySQLi和PDO二选一 —— 新项目推荐PDO,数据库迁移成本低

  4. 执行删除前可以先SELECT —— 拿不准条件对不对,先用相同WHERE查一遍看看要删哪些

  5. 事务配合使用 —— 重要数据删除前开启事务,删错了还能回滚

// 事务示例
$pdo->beginTransaction();
$stmt = $pdo->prepare("DELETE FROM accounts WHERE balance < 0");
$stmt->execute();
// 确认无误再提交
$pdo->commit();

关于SQL注入再说两句

很多人觉得小网站没人攻击,没必要用预处理。但我经手过好几个被黑的站点,都不是什么大站,就是普通企业站。攻击者用扫描工具批量跑,找到没过滤的输入框直接注入。

用预处理不是性能问题,是态度问题。

再补充一个常见错误:用mysqli_real_escape_string去转义,觉得这样就安全了。这个函数只处理字符转义,不改变SQL语法结构。某些编码情况下依然有绕过方法。预处理是经过编译的SQL模板,参数和数据分两次发送,从根本上杜绝了注入。

常见错误码和排查思路

错误信息 大概率原因
MySQL server has gone away 超时或数据包太大
Access denied 用户名密码不对
Table doesn't exist 表名写错或库不对
Cannot add or update a child row 外键约束导致删不了
Data too long for column 跟DELETE无关,一般是INSERT/UPDATE

遇到外键删不掉的,要么先删子表数据,要么临时关掉外键检查:

SET FOREIGN_KEY_CHECKS = 0;
DELETE FROM orders WHERE id = 10;
SET FOREIGN_KEY_CHECKS = 1;

做完记得重新打开。

← PHP更新MySQL数据记录:从基础到实践 PHP查询MySQL数据:SELECT语句 →
分享笔记 (共有 篇笔记)
验证码:
微信公众号