PDO查询返回0结果但phpMyAdmin中正常,求原因排查
这个问题我之前排查过好几次,核心原因大概率出在PDO的参数绑定方式上,具体来说有两个常见的坑:
1. bindParam()绑定的是变量引用而非当前值
bindParam()的作用是绑定变量的引用,而不是当前变量的具体值。如果在你调用bindParam()之后、execute()之前,$nelng、$swlng这些变量的值被意外修改了(比如后续代码重新赋值、或者变量作用域冲突),那实际执行SQL时用的就是修改后的值,自然和你在phpMyAdmin里测试的原始值不匹配,返回0结果。
2. 参数类型不匹配导致数值转换错误
默认情况下,bindParam()会把所有参数当作字符串类型(PDO::PARAM_STR)传递给MySQL。而你的经纬度字段(job_lat、job_lng)大概率是数值类型(比如DECIMAL、FLOAT),当字符串形式的数值和数据库里的数值进行范围匹配时,可能会出现隐式转换的精度问题,导致条件不成立。比如带有多位小数的数值,转换成字符串后可能和数据库存储的二进制数值匹配逻辑不一致。
解决方案
方案一:改用bindValue()绑定具体值
bindValue()会直接绑定变量当前的具体值,而非引用,同时可以指定更匹配的参数类型:
$get_markers = $pdo->prepare("SELECT tbl_jobs.job_id, tbl_jobs.job_lat, tbl_jobs.job_lng FROM tbl_jobs WHERE (CASE WHEN :swlat < :nelat THEN tbl_jobs.job_lat BETWEEN :swlat AND :nelat ELSE tbl_jobs.job_lat BETWEEN :nelat AND :swlat END) AND (CASE WHEN :swlng < :nelng THEN tbl_jobs.job_lng BETWEEN :swlng AND :nelng ELSE tbl_jobs.job_lng BETWEEN :nelng AND :swlng END)"); // 用bindValue绑定,同时指定参数类型 $get_markers->bindValue(":nelng", $nelng, PDO::PARAM_STR); $get_markers->bindValue(":swlng", $swlng, PDO::PARAM_STR); $get_markers->bindValue(":swlat", $swlat, PDO::PARAM_STR); $get_markers->bindValue(":nelat", $nelat, PDO::PARAM_STR); $get_markers->execute();
注意:如果你的经纬度是DECIMAL类型,用
PDO::PARAM_STR反而比PDO::PARAM_FLOAT更稳妥,因为字符串传递不会丢失精度,避免浮点误差。
方案二:保留bindParam()但确保类型正确+变量不被修改
如果你坚持用bindParam(),需要确保绑定后变量值没有被修改,同时显式指定参数类型:
$get_markers->bindParam(":nelng", $nelng, PDO::PARAM_STR); $get_markers->bindParam(":swlng", $swlng, PDO::PARAM_STR); $get_markers->bindParam(":swlat", $swlat, PDO::PARAM_STR); $get_markers->bindParam(":nelat", $nelat, PDO::PARAM_STR);
排查技巧
可以通过debugDumpParams()查看实际绑定的参数值和类型,对比phpMyAdmin里用的数值是否一致:
$get_markers->execute(); $get_markers->debugDumpParams(); // 打印绑定的参数详情
这会输出SQL语句和绑定的参数信息,帮你快速定位是不是参数值或类型出了问题。
内容的提问来源于stack exchange,提问作者Adam G

