MySQL预处理语句参数绑定无结果且PHP端触发only_full_group_by错误求助
问题原因
你遇到的问题核心是不同数据库连接的sql_mode配置不一致,和参数绑定逻辑本身没有关系。
- 为什么PHP执行报错、PHPMyAdmin不报错:
PHPMyAdmin建立数据库连接时会主动调整sql_mode参数,默认移除ONLY_FULL_GROUP_BY限制;而你的PHP代码用mysqli连接时,使用的是MySQL服务端默认配置,开启了ONLY_FULL_GROUP_BY。这个模式要求SELECT列表里的所有非聚合列,要么出现在GROUP BY子句中,要么和GROUP BY的列存在明确的函数依赖。你这条SQL的GROUP BY 仅使用了node.id,其他node表字段既没放在GROUP BY里,也没有加聚合函数,所以在PHP的连接下prepare阶段就直接失败了,$stmt返回false,后续的参数绑定、执行逻辑都没有运行,自然返回零条结果。
你之前误以为硬编码在PHP里能正常运行,实际上是因为测试时没有开启PHP的错误显示,看不到prepare失败的报错,你拿到的正常结果都是在PHPMyAdmin环境下执行得到的,硬编码的SQL放到PHP默认连接配置下一样会执行失败。 - 为什么一开始只看到返回空、后来才看到报错:
你后续应该调整了PHP的错误报告配置,开启了mysqli异常抛出,才看到了真实的Fatal Error,之前错误没有暴露,所以只能拿到空的结果集。
解决办法
方案1(推荐):修改SQL符合ONLY_FULL_GROUP_BY规范
对SELECT列表里所有非聚合、非GROUP BY的字段用ANY_VALUE()包裹,因为node.id是表的主键,同一node.id对应的其他字段都是固定的,用ANY_VALUE()包裹不会影响结果正确性,同时兼容SQL规范,示例如下:
SELECT node.id, ANY_VALUE(node.line_type) AS line_type, (COUNT(parent.id) - 1) AS depth, ANY_VALUE(node.visible_index) AS visible_index, ANY_VALUE(node.printed_no) AS printed_no, ANY_VALUE(node.line_text) AS line_text, ANY_VALUE(node.value_type) AS value_type, ANY_VALUE(node.left_index) AS left_index, ANY_VALUE(node.right_index) AS right_index, (SELECT COUNT(*) FROM bk_accounts a WHERE a.balance_and_income_line_id = node.id) AS account_count FROM bk_balance_and_income_lines AS parent LEFT JOIN bk_balance_and_income_lines AS node ON node.left_index BETWEEN parent.left_index AND parent.right_index WHERE node.ownerID = ? AND node.version_no = ? AND parent.ownerID = node.ownerID AND parent.version_no = node.version_no GROUP BY node.id ORDER BY node.left_index
方案2(不推荐):对齐连接的sql_mode配置
在PHP建立mysqli连接后,先执行一次SQL修改当前连接的模式,和PHPMyAdmin的运行环境对齐,原有SQL不需要修改也能执行:
$con->query("SET sql_mode = REPLACE(@@sql_mode, 'ONLY_FULL_GROUP_BY', '')");
内容的提问来源于stack exchange,提问作者ryanj
相关产品推荐
相关产品推荐

