PHP MySQL考勤嵌套IF查询无法触发第三条件优化求助
问题根因
- 你的嵌套查询逻辑存在致命判断错误:当记录的
STATUS已经为2时,第二层判断执行的是查询STATUS='1'的记录,此时查询结果为空,会直接进入else分支更新AMOUT并把STATUS重置为1,永远走不到STATUS=2对应的第三层判断,自然不会触发PMOUT的更新逻辑。 - 重复查询完全没有必要,第一次查询已经拿到了当日学生的考勤记录,直接读取
STATUS字段值做判断即可,无需再发起两次多余的SQL请求。 - 直接拼接SQL变量存在SQL注入风险,建议使用预处理语句优化。
优化后的实现代码
<?php // 开启预处理避免SQL注入 $stmt = $conn->prepare("SELECT STATUS FROM attendance WHERE STUDENTID = ? AND LOGDATE = ? LIMIT 1"); $stmt->bind_param("ss", $studentID, $date); $stmt->execute(); $result = $stmt->get_result(); if ($result->num_rows > 0) { $row = $result->fetch_assoc(); $currentStatus = $row['STATUS']; $updateSql = ''; // 根据当前STATUS判断要更新的字段 switch ($currentStatus) { case 0: $updateSql = "UPDATE attendance SET AMOUT = ?, STATUS = 1 WHERE STUDENTID = ? AND LOGDATE = ?"; break; case 1: $updateSql = "UPDATE attendance SET PMIN = ?, STATUS = 2 WHERE STUDENTID = ? AND LOGDATE = ?"; break; case 2: $updateSql = "UPDATE attendance SET PMOUT = ?, STATUS = 3 WHERE STUDENTID = ? AND LOGDATE = ?"; break; default: // STATUS=3说明当日打卡已经完成,可自定义提示逻辑 $_SESSION['error'] = "今日打卡已完成,无需重复打卡"; exit; } // 执行更新操作 $updateStmt = $conn->prepare($updateSql); $updateStmt->bind_param("sss", $time, $studentID, $date); if ($updateStmt->execute()) { $_SESSION['success'] = "打卡成功"; } else { $_SESSION['error'] = $conn->error; } } else { // 无记录插入首次打卡 $insertStmt = $conn->prepare("INSERT INTO attendance(STUDENTID, AMIN, LOGDATE, STATUS) VALUES (?, ?, ?, 0)"); $insertStmt->bind_param("sss", $studentID, $time, $date); if ($insertStmt->execute()) { $_SESSION['success'] = "打卡成功"; } else { $_SESSION['error'] = $conn->error; } }
优化说明
- 只需要一次查询即可拿到当前打卡状态,减少了数据库请求次数,提升执行效率
- 用
switch代替嵌套if,逻辑更清晰,避免嵌套层级过深出现判断错误 - 全程使用预处理语句,彻底避免SQL注入风险
- 补充了打卡完成后的拦截逻辑,避免STATUS=3之后还重复执行更新操作
内容的提问来源于stack exchange,提问作者John Arzaga
相关产品推荐
相关产品推荐

