You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 10中DB::raw为SQL函数加反引号致查询报错

解决Laravel 10中DB::raw为SQL函数添加反引号的查询错误

问题背景

从Laravel 9迁移到Laravel 10时,若为兼容修改whereIn中的DB::raw调用,额外添加->getValue(DB::getQueryGrammar()),会导致concat这类SQL函数表达式被自动加上反引号(如\concat(a_col, b_col)``),数据库会将其识别为列名,抛出错误:

Column not found: 1054 Unknown column 'concat(a_col, b_col)' in 'IN/ALL/ANY subquery'

原Laravel 9中的查询示例:

$query = DB::table('table_a')
->join('table_b', 'table_b.id', '=', 'table_a.col_c')
->select([
    'table_b.c_id',
    DB::raw('COUNT(DISTINCT(col_c)) AS any_count'),
    DB::raw('COUNT(CASE WHEN col_b = 1 THEN 1 END) AS one_count'),
    DB::raw('COUNT(CASE WHEN col_b = 2 THEN 1 END) AS two_count'),
])
->where('col_d', '=', ColD::class)
->where('col_e', '=', true)
->whereIn(DB::raw('concat(col_a, col_b, col_c)'), function ($query) {
    $query->from('table_a as latest_table_a')
          ->selectRaw('concat(max(col_a), col_b, col_c) as max_unique_cols')
          ->whereColumn('col_d', 'table_a.col_d')
          ->whereColumn('col_c', 'table_a.col_c')
          ->groupBy('col_d', 'col_c', 'col_b');
})
->groupBy('table_b.c_id');

解决方案

方案1:移除getValue调用,直接传递DB::raw实例

Laravel 10的查询构建器仍支持直接将DB::raw(即Illuminate\Database\Query\Expression实例)作为whereIn的第一个参数,无需手动调用getValue转成字符串。修正后的代码如下:

$query = DB::table('table_a')
->join('table_b', 'table_b.id', '=', 'table_a.col_c')
->select([
    'table_b.c_id',
    DB::raw('COUNT(DISTINCT(col_c)) AS any_count'),
    DB::raw('COUNT(CASE WHEN col_b = 1 THEN 1 END) AS one_count'),
    DB::raw('COUNT(CASE WHEN col_b = 2 THEN 1 END) AS two_count'),
])
->where('col_d', '=', ColD::class)
->where('col_e', '=', true)
// 直接传递DB::raw实例,无需调用getValue
->whereIn(DB::raw('concat(col_a, col_b, col_c)'), function ($query) {
    $query->from('table_a as latest_table_a')
          ->selectRaw('concat(max(col_a), col_b, col_c) as max_unique_cols')
          ->whereColumn('col_d', 'table_a.col_d')
          ->whereColumn('col_c', 'table_a.col_c')
          ->groupBy('col_d', 'col_c', 'col_b');
})
->groupBy('table_b.c_id');

此方式下查询构建器会正确识别这是原生SQL表达式,不会添加多余反引号。

方案2:改用whereRaw编写完整条件

如果需要更灵活的SQL控制,可直接用whereRaw编写整个IN条件的SQL片段,彻底避免查询构建器的自动转义:

$query = DB::table('table_a')
->join('table_b', 'table_b.id', '=', 'table_a.col_c')
->select([
    'table_b.c_id',
    DB::raw('COUNT(DISTINCT(col_c)) AS any_count'),
    DB::raw('COUNT(CASE WHEN col_b = 1 THEN 1 END) AS one_count'),
    DB::raw('COUNT(CASE WHEN col_b = 2 THEN 1 END) AS two_count'),
])
->where('col_d', '=', ColD::class)
->where('col_e', '=', true)
->whereRaw('concat(col_a, col_b, col_c) IN (
    SELECT concat(max(col_a), col_b, col_c)
    FROM table_a as latest_table_a
    WHERE latest_table_a.col_d = table_a.col_d
      AND latest_table_a.col_c = table_a.col_c
    GROUP BY col_d, col_c, col_b
)')
->groupBy('table_b.c_id');

说明

之前添加getValue的操作属于冗余操作,Laravel 10的whereIn方法仍支持接收Expression类型参数,调用getValue会将表达式转为普通字符串,导致查询构建器误判为列名并添加反引号。

内容的提问来源于stack exchange,提问作者AndyW

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 18:35:09