PHP执行INSERT返回成功,但数据库未新增记录的问题排查
这种情况在PDO数据库操作里其实挺常见的,我来帮你拆解几个最可能的原因:
1. 你可能判断的是prepare()的结果,而非execute()的结果
看你的代码片段,假设你是这么写的:
$query = $this->db->prepare($sql); if ($query) { // 绑定参数... // 但可能忘了调用execute(),或者execute()失败了却没检查 }
prepare()只要SQL语法没明显错误就会返回true,但真正执行插入动作的是execute()方法。如果没调用execute(),或者execute()返回false但你没做判断,那数据库自然不会有新记录,但if ($query)会顺利通过。
正确的做法应该是检查execute()的返回值:
$query = $this->db->prepare($sql); $query->bindParam(':id', $id); // 绑定其他参数... if ($query->execute()) { // 执行成功的逻辑 } else { // 打印错误信息排查问题 var_dump($query->errorInfo()); }
2. 事务未提交
如果你的代码里开启了PDO事务(比如调用过$db->beginTransaction()),但插入操作后没有执行$db->commit(),那么即使execute()返回true,数据库也不会持久化这条记录——因为事务还没提交,一旦脚本结束或者触发了rollback(),这条待插入的记录就会被丢弃。
检查一下你的代码中是不是有事务逻辑,比如:
$this->db->beginTransaction(); // 执行插入操作 // 但忘了写 $this->db->commit();
3. 插入的记录被忽略或更新了(而非新增)
如果user_mileage表有唯一约束(比如user_id是唯一键,或者user_id+alias是组合唯一键),而你插入的是重复数据,同时SQL里用了INSERT IGNORE或者ON DUPLICATE KEY UPDATE,那么execute()会返回true,但数据库不会新增记录——要么跳过这条插入请求,要么更新了已有的行。
你可以检查完整的SQL语句是否带有IGNORE,或者查看表的唯一键约束。另外可以用$db->lastInsertId()验证:如果插入成功,这个方法会返回新行的ID;如果是更新或被忽略,可能返回0或者已有行的ID。
4. 连接的数据库不是你查看的那个
这种低级错误也很容易犯:比如代码连接的是测试环境的数据库,但你却在生产环境的数据库里找记录,或者反过来。可以在代码里打印当前连接的数据库名称验证:
echo $this->db->query('SELECT database()')->fetchColumn();
5. PDO错误模式未开启,隐藏了实际错误
默认情况下,PDO不会抛出异常,只会返回错误码。如果插入操作因为字段类型不匹配、字段为空但不允许null等原因失败了,但你没开启错误模式,execute()可能依旧返回true(或者返回false但你没检查),同时数据库不会插入记录。
可以在初始化PDO连接时开启异常模式,这样能快速定位问题:
$db = new PDO($dsn, $user, $pass, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ]);
快速排查步骤
你可以按照这个顺序排查:
- 先确认你检查的是
execute()的返回值,而不是prepare()的 - 开启PDO异常模式,看是否有错误抛出
- 检查是否有未提交的事务
- 验证表的唯一约束和SQL语句是否包含
IGNORE/ON DUPLICATE - 确认代码连接的数据库和你查看的是同一个
内容的提问来源于stack exchange,提问作者Jumana Alhaddad

