PHP执行MySQL查询无返回结果,手动执行该查询却有结果的问题
咱们先来拆解你遇到的这个诡异问题:你的PHP API生成的SQL语句在phpMyAdmin里能正常查到1条数据,但API执行后却返回num_rows: 0和locations: null,同时mysqli对象的affected_rows显示为1——这明显矛盾,对吧?下面咱们一步步找原因、解决问题。
可能的核心原因
1. 字符集/编码不匹配
你直接用$_POST参数拼接SQL,虽然返回的SQL看起来和phpMyAdmin里的一致,但如果PHP数据库连接的字符集和phpMyAdmin使用的字符集不一致,会导致查询时的隐式编码转换问题。比如phpMyAdmin用utf8mb4,但你的PHP连接没设置字符集,user_id或date的字符串在查询时出现隐形编码差异,导致匹配不到数据。
2. 隐形字符干扰
AJAX传递的user或date参数可能包含不可见字符(比如空格、换行、全角空格),这些字符在JSON输出里看不到,但会让SQL的匹配条件失效。而你在phpMyAdmin里手动输入的参数是干净的,所以能查到数据。
3. 直接拼接SQL的潜在风险
直接把用户输入拼到SQL里不仅有严重的SQL注入风险,还容易因为参数转义不彻底、特殊字符处理不当,导致查询逻辑和预期不符。
解决步骤
第一步:统一数据库连接字符集
在数据库连接成功后,立即设置和你的数据库/表一致的字符集(比如utf8mb4,这是当前主流的兼容表情的字符集):
$conn->set_charset('utf8mb4');
你可以在phpMyAdmin里查看数据库或locations表的字符集,确保PHP连接的字符集和它完全一致。
第二步:改用预处理语句(彻底解决问题+防注入)
预处理语句会自动处理参数的转义、字符集适配,完全避免手动拼接SQL的各种坑。修改后的代码如下:
<?php $response['is_error'] = 'no'; $user = $_POST['user']; $date = $_POST['date']; // 使用预处理语句,用占位符替代直接拼接 $sql = "select * from locations where user_id = ? and DATE(timestamp) = ?"; $stmt = $conn->prepare($sql); // 检查预处理语句是否创建成功 if (!$stmt) { $response['is_error'] = 'yes'; $response['status'] = "failed"; $response['error'] = $conn->error; echo json_encode($response); exit; } // 绑定参数,"ss"表示两个参数都是字符串类型 $stmt->bind_param("ss", $user, $date); $stmt->execute(); // 获取结果集并处理 $result = $stmt->get_result(); $response['num_rows'] = $result->num_rows; $response['locations'] = $result->fetch_assoc(); $response['date'] = $date; // 处理错误状态 if($response['is_error'] == 'yes'){ $response['status'] = "failed"; $response['error'] = $conn->error; }else{ $response['status'] = "ok"; } $response['sql'] = $sql; // 这里的SQL是带占位符的,用于调试 echo json_encode($response); ?>
第三步:调试参数的真实内容
如果还是有问题,可以在代码里加入参数调试,看看是否有隐形字符:
// 新增调试字段,查看参数的真实长度和十六进制编码 $response['user_debug'] = [ 'value' => $user, 'length' => strlen($user), 'hex' => bin2hex($user) ]; $response['date_debug'] = [ 'value' => $date, 'length' => strlen($date), 'hex' => bin2hex($date) ];
比如正常的0123456789十六进制编码是30313233343536373839,如果返回的hex长度更长,说明参数里有隐形字符,需要在前端处理参数时做trim或过滤。
第四步:检查timestamp字段类型
确保locations表的timestamp字段是DATETIME或TIMESTAMP类型,而不是VARCHAR。如果是字符串类型,DATE(timestamp)的转换逻辑可能和phpMyAdmin的自动处理不一致,导致匹配失败。
为什么phpMyAdmin能查到数据?
phpMyAdmin在执行查询时会自动处理字符集、参数转义,而且你手动输入的参数是干净无隐形字符的;而AJAX传递的参数可能存在编码问题或隐形字符,导致PHP拼接的SQL看起来和phpMyAdmin里的一样,但实际执行时匹配不到数据。
内容的提问来源于stack exchange,提问作者Rishabh Gusain




