Laravel 5.6查询MySQL 5.7 JSON字段出现SQLSTATE[HY000]异常求助
嘿,这个问题我之前帮朋友排查过类似的,咱们来拆解下怎么解决——其实不一定非要用原生语句,先搞清楚错误根源:SQLSTATE[HY000]: General error: 2036 通常是PDO驱动在处理MySQL JSON类型字段时的类型映射冲突导致的,Laravel 5.6的查询构建器默认没有自动适配这种类型,所以PDO无法正确解析返回的JSON结果。
给你几个实用的解决方案,按优先级排序:
1. 查询时显式转换JSON字段为字符串
在select里用DB::raw把JSON字段转成字符串类型,让PDO能正确处理:
$transactions = DB::table('transactions') ->select( DB::raw('CAST(transactions.uuids_json AS CHAR) AS uuids_json'), // 这里放你的其他列 'transactions.id', 'transactions.created_at' ) // 后续的查询条件... ->get();
拿到结果后,你可以用json_decode($transaction->uuids_json, true)把字符串转回PHP数组使用,完全不影响业务逻辑。
2. 全局配置PDO字符串化所有查询结果
如果你的项目里有很多JSON字段需要处理,可以修改config/database.php中mysql的配置项,添加PDO的字符串化选项:
'mysql' => [ // 其他配置... 'options' => [ PDO::MYSQL_ATTR_STRINGIFY_FETCHES => true, ], ],
这个配置会让PDO把所有查询结果都转成字符串,自然也包括JSON字段,不过要注意这是全局设置,可能会影响其他数值类型字段的处理(比如int类型会变成字符串),需要根据项目情况权衡。
3. 用Laravel的JSON查询方法(如果需要条件筛选)
要是你后续需要对uuids_json做条件查询(比如查找包含某个UUID的记录),直接用Laravel 5.6支持的whereJsonContains方法就行,它会自动处理类型适配,不会触发2036错误:
$transactions = DB::table('transactions') ->select('uuids_json', '...其他列') ->whereJsonContains('uuids_json', '1a7b29b8-5009-4266-8192') ->get();
什么时候需要用原生语句?
只有当上述方法都无法满足你的复杂JSON操作需求时,才考虑用原生SQL,比如:
$transactions = DB::select('SELECT uuids_json, id, created_at FROM transactions WHERE ...');
但一般来说,前面的方法足够覆盖大部分场景,还能保持Laravel查询构建器的可读性和可维护性。
内容的提问来源于stack exchange,提问作者zer02

