Laravel Raw Select返回重复值问题排查与解决
Laravel查询JSON列长度返回重复结果的问题解决
问题重现
我在模型中编写了测试方法,用于获取指定行JSON列的长度:
public function test(){ return $this->select(DB::raw('JSON_LENGTH((SELECT comments FROM lab_evals WHERE id='.$this->id.'))'))->get(); }
在tinker中执行后,返回了包含重复对象的集合:
= Illuminate\Database\Eloquent\Collection {#7430 all: [ App\Models\LabEval {#7429 JSON_LENGTH((SELECT comments FROM lab_evals WHERE id =50)): 2, }, App\Models\LabEval {#7431 JSON_LENGTH((SELECT comments FROM lab_evals WHERE id =50)): 2, }, ], }
预期结果应该只包含一个对象。
原因分析
查看Laravel生成的原生SQL,找到了问题根源:
"select JSON_LENGTH((SELECT comments FROM lab_evals WHERE id=50)) from `lab_evals`"
这条SQL会遍历lab_evals表的每一行,每行都执行一次子查询计算JSON长度,所以表中有多少行,就会返回多少个重复结果。而正确的SQL应该是直接执行子查询获取单个值:
(SELECT JSON_LENGTH((SELECT comments from lab_evals WHERE id=50)));
解决方法
改用DB::select()直接执行原生SQL,避免Laravel自动拼接from子句:
DB::select('SELECT JSON_LENGTH((SELECT comments from lab_evals WHERE id='.$this->id.'))')
补充:为避免SQL注入风险,推荐使用参数绑定的写法:
DB::select('SELECT JSON_LENGTH((SELECT comments from lab_evals WHERE id=?))', [$this->id])
内容的提问来源于stack exchange,提问作者smallpop
相关产品推荐
相关产品推荐

