pdo::errorcode()仅反映连接层或直接句柄操作错误,prepare()+execute()的sql错误需用pdostatement::errorcode();errorinfo()返回含sqlstate、驱动码、可读消息的数组,调试更实用;错误处理应按模式选择:开发用errmode_exception,生产需降级时用静默模式+手动检查。

PDO::errorCode() 和 PDOStatement::errorCode() 不是万能的,必须匹配调用对象
直接在 PDO 实例上调用 PDO::errorCode() 只能拿到数据库连接层或 exec()、query() 这类直接作用于句柄的操作错误。如果你用了 prepare() + execute(),错误实际发生在 PDOStatement 对象上,此时 $pdo->errorCode() 仍返回 '00000' 或上一次连接/事务操作的残留值,完全不反映 SQL 执行失败。
- 查表不存在、字段名写错、类型不匹配等语句级错误,必须检查
$stmt->errorCode(),不是$pdo->errorCode() -
PDO::errorCode()对prepare()本身失败(如语法错误)有效;但对execute()失败无效 - SQL Server 驱动下,成功连接会返回
'01000'(警告),不代表出错,别误判为失败
errorInfo() 比 errorCode() 更实用,因为它带具体消息
PDO::errorInfo() 和 PDOStatement::errorInfo() 返回三元素数组:[SQLSTATE, 驱动错误码, 错误消息]。其中 $info[2] 就是 MySQL 的 ERROR 1146 (42S02): Table 'xxx' doesn't exist 这种可读信息,比纯五位码直观得多。
- 静默模式(默认)下,
errorInfo()是唯一能拿到错误详情的方式 -
$info[0]和errorCode()返回值一致,但$info[2]才是调试关键 - 不要只判断
errorCode() !== '00000'就结束——有些驱动对警告也返回非'00000'值(如'01000'),得结合$info[1]和$info[2]综合判断是否真失败
三种错误处理模式决定你是否需要手动检查
默认静默模式(PDO::ERRMODE_SILENT)下,所有操作失败都不中断脚本,必须显式调用 errorCode() 或 errorInfo();而设成 PDO::ERRMODE_EXCEPTION 后,任何错误都会抛出 PDOException,try/catch 捕获即可,不用每步都查。
- 开发阶段强烈建议设为
PDO::ERRMODE_EXCEPTION:$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) - 生产环境若需精细控制(比如某条查询失败就降级,不崩整个页面),才用静默模式+手动检查
-
PDO::ERRMODE_WARNING很少用:PHP warning 写进错误日志但不中断流程,容易漏掉,且无法捕获消息内容
prepare/execute 场景下最容易漏掉的检查点
写错表名、字段名、参数绑定类型不匹配,这些都在 execute() 时才暴露。很多人只在 prepare() 后检查,却忘了 execute() 也可能失败。
- 正确姿势:
$stmt = $pdo->prepare($sql); $stmt->execute($params); if ($stmt->errorCode() !== '00000') { /* 处理 */ } - 更稳妥写法:
if (!$stmt->execute($params)) { $err = $stmt->errorInfo(); error_log("SQL failed: {$err[2]}"); } - 注意:如果
$params是空数组或 null,某些驱动可能不触发错误,但数据没插进去——得额外验证影响行数($stmt->rowCount())
真正容易被忽略的是:错误归属对象(PDO vs PDOStatement)和错误发生时机(prepare 时 vs execute 时)必须严格对应,否则查半天 errorCode() 都是 '00000'。











