使用AJAX调用mysqli时,含NOW()的UPDATE触发500错误的问题
遇到这种加了NOW()就触发500错误、去掉就正常的情况,大概率是服务器端的SQL执行出了问题,但因为没开启错误提示,所以只看到模糊的500状态码。咱们一步步来排查:
第一步:先开启错误显示,获取具体错误信息
500错误是服务器内部错误,默认可能不会显示具体原因,先在stop_duty.php开头加上这段代码,让PHP显示详细错误:
error_reporting(E_ALL); ini_set('display_errors', 1);
同时,在你的MySQLi执行语句后加上错误捕获,这样能直接看到SQL执行的问题:
$delete_row = $mysqli->query("UPDATE combats_duty_logs SET active= '0', duty_time_stop= NOW() WHERE id=".$idToDelete); if (!$delete_row) { die("SQL执行错误: " . $mysqli->error); }
这一步能帮你快速定位到底是语法问题、字段类型问题还是其他错误。
最可能的几个原因
1. duty_time_stop字段类型不匹配
如果duty_time_stop字段不是DATETIME、TIMESTAMP这类时间类型(比如是VARCHAR、INT),那用NOW()返回的YYYY-MM-DD HH:MM:SS格式字符串去赋值就会触发SQL错误,导致服务器返回500。而去掉NOW()后,只更新active字段(应该是INT类型),SQL能正常执行,所以功能正常。
解决方法:检查数据库表结构,把duty_time_stop改成DATETIME或TIMESTAMP类型;如果必须用其他类型,就把NOW()转成对应格式(比如用UNIX_TIMESTAMP()转成时间戳,如果字段是INT的话)。
2. SQL注入风险导致的语法错误
你现在的SQL语句是直接拼接$idToDelete,如果$idToDelete没有被正确过滤(比如前端传过来的不是数字,或者有特殊字符),会导致SQL语法错误。比如如果$idToDelete是空值,SQL就变成:
UPDATE combats_duty_logs SET active= '0', duty_time_stop= NOW() WHERE id=
这明显是语法错误,会触发500。
解决方法:用预处理语句来避免注入同时保证语法正确:
$stmt = $mysqli->prepare("UPDATE combats_duty_logs SET active= 0, duty_time_stop= NOW() WHERE id=?"); $stmt->bind_param("i", $idToDelete); $stmt->execute(); $stmt->close();
这样不管$idToDelete是什么类型,都会被正确处理,避免语法错误。
3. MySQL时区配置问题
少数情况下,MySQL的时区配置不正确,导致NOW()无法正常生成时间值。可以通过执行SELECT @@global.time_zone, @@session.time_zone;查看当前时区,或者在连接MySQL后手动设置时区:
$mysqli->query("SET time_zone = '+8:00'"); // 换成你所在的时区,比如UTC+8
总结
先开启错误显示和SQL错误捕获,这是最快找到问题的方法。其中字段类型不匹配和SQL语法错误(拼接导致)是最常见的原因,建议优先排查这两点。
内容的提问来源于stack exchange,提问作者Влад Мазур

