PHP如何捕获SQL 1062重复主键异常并输出自定义提示?
问题解决方法
现有代码的问题点
- PDO未开启异常抛出模式:PDO默认采用静默错误处理模式,出现SQL错误时不会主动抛出异常,因此你的catch块无法触发
- 错误码取值逻辑错误:
PDOException::getCode()返回的是SQLSTATE通用错误码(主键重复对应值为23000),你需要的1062是MySQL专属错误编号,要从异常的errorInfo属性的第二个元素获取 - 重复捕获相同类型异常:代码中连续两次捕获
PDOException属于语法错误,只会执行第一个catch块 - 未输出自定义提示:catch块中只写了提示文本,没有加
echo语句,自然不会在页面展示内容 - 输入转义逻辑错误:
htmlspecialchars是用于输出到前端时防止XSS的函数,不应该在接收输入时使用,会导致存入数据库的数据被错误转义
修改步骤
1. 调整PDO初始化配置(修改dataBasePage.php文件)
在创建PDO连接后,新增异常模式配置,确保SQL错误会抛出PDOException:
// 原有PDO连接代码 $db = new PDO('mysql:host=你的数据库地址;dbname=你的库名;charset=utf8mb4', '数据库用户名', '数据库密码'); // 新增下面这行开启异常模式 $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
2. 修改业务代码逻辑
完整修改后的业务代码如下:
<?php include('topNavigation.php'); echo "<br>"; // 接收输入时仅做 trim 处理,输出时再做XSS转义 $symbol = trim(filter_input(INPUT_POST, 'symbol')); $company_name = trim(filter_input(INPUT_POST, 'company_name')); $current_price = filter_input(INPUT_POST, 'current_price', FILTER_VALIDATE_FLOAT); if ($symbol == '' || $company_name == '' || $current_price === false || $current_price < 0.0) { echo "请填写所有字段且输入合法数据,请重试。"; } else { try { require('dataBasePage.php'); $query = "insert into stock (`symbol`, `company_name`, `current_price`) values (:symbol, :company_name, :current_price)"; $statement = $db->prepare($query); $statement->bindValue(':symbol', $symbol); $statement->bindValue(':company_name', $company_name); $statement->bindValue(':current_price', $current_price); $statement->execute(); $statement->closeCursor(); // 输出到前端时再加htmlspecialchars做XSS防护 echo htmlspecialchars($symbol) . ' 对应公司 ' . htmlspecialchars($company_name).' 新增成功<br>'; } catch (PDOException $ex){ // 从errorInfo中取MySQL专属错误码 if (($ex->errorInfo[1] ?? 0) == 1062 ) { echo "股票代码已存在,请重新输入"; } else { echo "连接错误: " . $ex->getMessage(); } } } ?>
内容的提问来源于stack exchange,提问作者Brian Ball
相关产品推荐
相关产品推荐

