将INSERT查询放入if条件时出现重复插入问题及代码逻辑咨询
我来帮你分析下你遇到的重复插入问题,结合你给出的代码逻辑,大概率是以下几个原因导致的,咱们一步步来排查解决:
可能的问题根源
1. 存在性检查的查询逻辑不严谨
你用$get_id_siswa来判断学生是否存在,但如果这个查询的条件不够精准,就会出现“明明学生已经存在,但查询返回空”的情况,导致多次触发插入操作。比如你只根据姓名查询,但姓名可能重复;或者查询时漏了某个唯一标识字段(比如学号、身份证号),都会让判断失效。
2. 并发请求引发的竞态条件
如果你的系统有多个请求同时处理同一个学生的插入,就可能出现:第一个请求刚检查完“学生不存在”,还没完成插入操作,第二个请求也做了同样的检查,也得到“不存在”的结果,于是两个请求都执行了插入,最终产生重复数据。
3. 分支判断的变量混淆
看你代码里的else if用了$get_id_asesi这个变量,但前面的判断用的是$get_id_siswa——这两个变量是不是来自同一个查询?如果是不同的查询结果,很可能出现判断逻辑不一致的情况,本该走更新分支的场景,却误走了插入分支。
具体解决方案
方案1:完善存在性检查的查询条件
确保$get_id_siswa的查询使用业务上绝对唯一的字段组合,比如学号+身份证号,这样能精准判断学生是否存在。示例代码:
// 示例:用学号(nis)和身份证号(nik)作为唯一判断条件 $get_id_siswa = $this->db->where('nis', $nis) ->where('nik', $nik) ->get('siswa') ->row();
方案2:给数据库表加唯一约束
这是最稳妥的兜底方案,就算代码逻辑有漏洞,数据库层面也能直接阻止重复插入。你可以在学生表的唯一字段(比如nik、nis)上添加唯一索引:
ALTER TABLE siswa ADD UNIQUE INDEX idx_unique_siswa (nik, nis);
之后如果再出现重复插入,数据库会抛出错误,你可以在代码中捕获这个错误,转而执行更新操作。
方案3:用INSERT ... ON DUPLICATE KEY UPDATE简化逻辑
这种方式不需要先查询再判断,直接让数据库自动处理插入或更新,完美避免竞态条件。示例代码:
// 构建要插入/更新的数据 $datax = [ 'nis' => $nis, 'nama_lengkap' => $nama_lengkap, // 其他字段... ]; // 执行插入,若重复则更新 $this->db->insert('siswa', $datax); if ($this->db->affected_rows() == 0) { // 插入失败(因为重复),执行更新 $this->db->where('nis', $nis) ->where('nik', $nik) ->update('siswa', $datax); } // 或者直接写原生SQL(更高效) $sql = "INSERT INTO siswa (nis, nama_lengkap, ...) VALUES (?, ?, ...) ON DUPLICATE KEY UPDATE nama_lengkap=?, ..."; $this->db->query($sql, [$nis, $nama_lengkap, ..., $nama_lengkap, ...]);
方案4:检查变量一致性
确认$get_id_siswa和$get_id_asesi是不是同一个查询的结果,避免因为变量名写错或者查询逻辑不同,导致判断分支出错。比如你是不是本来应该用$get_id_siswa来做else if的判断,却误写成了$get_id_asesi?
快速排查建议
你可以先在if(!$get_id_siswa)这行代码前,加上var_dump($get_id_siswa); die();,看看当学生已经存在时,这个变量是不是真的返回了非空值——这能快速定位是不是存在性检查的问题。
内容的提问来源于stack exchange,提问作者سلطان

