PHP for循环批量插入MySQL时第二个员工ID数据未入库
问题现象
- 传入参数:
empBCTID:BCT-303, BCT-302Year: 2023SMonth: 6Emonth: 12
- 实际表现:代码执行时循环遍历的输出日志全部打印完成,无PHP报错,最终返回
{"message":"Employee Added"}成功响应;但数据库中仅写入了第一个员工BCT-303的6-12月数据,第二个员工BCT-302的对应数据全部未入库。
根因定位
- ID拆分后存在多余前导空格:代码使用
explode(',', $empBCTID)按逗号拆分员工ID,但传入参数中逗号后带有半角空格,拆分得到的第二个数组元素实际值为BCT-302(开头多1个空格),并非预期的BCT-302。该细节可以从日志中直接验证:BCT-303的日志行是6ContinueBCT-303...(Continue和BCT之间无空格),BCT-302的日志行是6Continue BCT-302...(Continue和BCT之间多了1个空格,就是$bctid自带的前导空格)。如果empreporttest表的empBCTID字段设置了长度限制、唯一约束,带前导空格的ID会触发字段截断、唯一键冲突,导致插入失败。 - SQL执行无错误检查,错误被静默吞掉:代码中调用
prepare、bind_param、execute后均未判断返回值,也没有开启MySQLi的错误抛出机制,因此SQL插入失败时不会输出任何报错信息——日志中打印的Continue仅代表代码执行到了echo语句,不代表前面的插入SQL执行成功。 - 循环外存在多余的重复执行逻辑:两层循环结束后,代码额外调用了一次
$stmt->execute(),会重复执行最后一次绑定的插入语句,容易引发重复数据问题。
修复方案
- 拆分ID后对每个元素做首尾去空格处理,消除多余空白字符的影响
- 开启MySQLi异常报错模式,让SQL执行错误可以直接抛出,避免静默失败
- 将prepare操作移到循环外,避免重复创建语句句柄,提升执行性能
- 删除循环外多余的
execute调用,避免重复插入
修复后的参考代码:
// 建议在数据库连接初始化时就开启异常报错,后续所有SQL操作出错都会直接抛出异常 // $this->con->report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); function addempreport($empBCTID, $Year, $SMonth, $Emonth){ // 拆分ID后批量去除每个ID的首尾空白字符 $arr = array_map('trim', explode(',', $empBCTID)); $AttString = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; // 循环外提前预处理插入语句,无需每次循环重复prepare $stmt = $this->con->prepare("INSERT INTO empreporttest (empBCTID, Year, Month, AttString) VALUES (?, ?, ?, ?)"); $stmt->bind_param("siis", $bctid, $Year, $x, $AttString); for($i = 0; $i < count($arr); $i++) { $bctid = $arr[$i]; for ($x = $SMonth; $x <= $Emonth; $x++) { $stmt->execute(); } } $stmt->close(); return true; }
内容的提问来源于stack exchange,提问作者SNAD
相关产品推荐
相关产品推荐

