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

PostgreSQL下Eloquent ORM生成双引号致列不存在错误的解决咨询

PostgreSQL & Laravel Eloquent: 解决字符串被双引号包裹引发的"列不存在"错误

先给你理清楚问题根源:PostgreSQL里的双引号和单引号是完全不同的用途——双引号用来包裹表名、列名这类标识符,而单引号才是用来定义字符串常量的。你之前写的"registration"会被PostgreSQL当成一个叫registration的列来查找,自然就抛出column "registration" does not exist的错误了。

再看你的Eloquent代码,问题出在whereColumn这个方法的误用:whereColumn是专门用来做列与列之间的比较的(比如sub.created_at = other_table.updated_at),当你把字符串常量传给它时,它会错误地把常量当成列名,用双引号包裹起来,这就是触发错误的直接原因。

解决方案

只需要把代码里的whereColumn换成where,再调整一下时间条件的处理方式(不要手动转字符串),就能解决问题:

修改后的代码如下:

$set = DB::query()->fromSub(function ($query) { 
    $query->from('customers')
          ->select(
              'customer_event_types.code', 
              'customer_events.customer_id', 
              'customer_events.data', 
              DB::raw('count(customer_events.id) event_count'), 
              DB::raw('max(customer_events.created_at) created_at')
          )
          ->join('customer_events', 'customer_events.customer_id', '=', 'customers.id')
          ->join('customer_event_types', 'customer_events.customer_event_type_id', 'customer_event_types.id')
          ->groupBy('customer_event_types.code', 'customer_events.customer_id', 'customer_events.data')
          ->having(DB::raw('count(customer_events.id)'), '=', 1); 
}, 'sub')
->select('sub.code', 'sub.customer_id', 'sub.data', 'sub.event_count', 'sub.created_at')
->when($firstItem, function ($query, $events) { 
    // 动态生成WHERE条件
    foreach ($events as $event) {
        $query->where("sub.code", "=", (string)$event->event_code);
        
        if (isset($event->after_than_minutes_ago) && !empty($event->after_than_minutes_ago) && is_numeric($event->after_than_minutes_ago)) {
            // 直接传Carbon实例,Eloquent会自动处理成正确的SQL格式
            $query->where("sub.created_at", '>', Carbon::now()->subMinutes($event->after_than_minutes_ago));
        }
        
        if (isset($event->before_than_minutes_ago) && !empty($event->before_than_minutes_ago) && is_numeric($event->before_than_minutes_ago)) {
            $query->where("sub.created_at", '<', Carbon::now()->subMinutes($event->before_than_minutes_ago));
        }
    }
    return $query;
})
->get();

为什么这样改?

  1. where方法的作用:where是Laravel里用来比较列和常量值的标准方法,它会自动识别右边的字符串/数值/日期类型,用单引号正确包裹字符串常量,生成的SQL会变成sub.code = 'registration',符合PostgreSQL的语法要求。
  2. Carbon实例的直接传递:不需要把Carbon对象转成字符串,Eloquent会自动将其转换为PostgreSQL支持的时间格式,避免手动转换可能带来的格式错误或引号问题。

这样修改后,你的查询就能正常执行,不会再触发"列不存在"的错误了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:19:21