【问题标题】:Eloquent: Alias from outer query can't be referenced in subquery雄辩:外部查询的别名不能在子查询中引用
【发布时间】:2019-06-21 08:54:44
【问题描述】:

我有以下疑问:

DB::table('dining_tables as dt')
        ->whereNotExists(function($query){
            $query
                ->from('booking_allocations as ba')
                ->join('time_slots as ts', 'ba.slot_id', '=', 'ts.id')
                ->where('ba.booking_date', '=', '2019-01-27')
                ->where('ts.start_time', '>=', '12:00 PM')
                ->where('ts.end_time', '<=', '1:00 PM')
                ->where('ba.table_id', '=', 'dt.id')
                ->select(DB::raw('null'));
        })
        ->where('dt.capacity', '>=', 4)
        ->select('id')
        ->limit(1)
        ->get();

请注意,在外部查询中创建的别名 dt 正在以下行的子查询中被引用:

->where('ba.table_id', '=', 'dt.id')

这给我留下了以下错误:

使用消息“SQLSTATE [22P02] 照亮/数据库/查询异常: 无效的文本表示:7 错误:无效的输入语法 integer: "dt.id" (SQL: select "id" from "dining_tables" as "dt" where 不存在(从“booking_allocations”中选择 null 作为“ba”内部连接 "time_slots" 为 "ba" 上的 "ts"。"slot_id" = "ts"."id" 其中 "ba"."booking_date" = 2019-01-27 和 "ts"."start_time" >= 12:00 PM 和 "ts"."end_time" = 4 限制 1)'

我花了半天时间才意识到这个替换代码可以绕过错误:

->where('ba.table_id', '=', DB::raw('dt.id'))

注意:DB::raw() 围绕有问题的别名进行包装。

现在,查询按预期工作。我想了解这里可能发生的情况。

【问题讨论】:

  • 当你使用函数外部的变量时,你必须使用use($variable)和函数。
  • 你是对的,只是他没有这样做。

标签: laravel laravel-5 eloquent


【解决方案1】:

whereNotExists 在内部进行单独的查询:

https://github.com/laravel/framework/blob/5.7/src/Illuminate/Database/Query/Builder.php#L1435 https://github.com/laravel/framework/blob/5.7/src/Illuminate/Database/Query/Builder.php#L1404 https://github.com/laravel/framework/blob/5.7/src/Illuminate/Database/Query/Builder.php#L2772

dt 只有 db builder 的“更高”实例知道。

因此,db builder 在您的嵌套 where 中将其视为字符串,并且由于 ba.table_id 是整数,因此无法在该上下文中使用 string 类型的值。

当您使用 db raw 时 - 它只是将其按原样放入 sql 中,并按预期工作。

【讨论】:

    猜你喜欢
    • 2014-04-12
    • 2023-02-02
    • 2019-04-23
    • 2021-04-19
    • 1970-01-01
    • 2015-12-13
    • 2015-07-07
    • 2018-01-26
    • 2021-07-23
    相关资源
    最近更新 更多