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();
为什么这样改?
where方法的作用:where是Laravel里用来比较列和常量值的标准方法,它会自动识别右边的字符串/数值/日期类型,用单引号正确包裹字符串常量,生成的SQL会变成sub.code = 'registration',符合PostgreSQL的语法要求。- Carbon实例的直接传递:不需要把Carbon对象转成字符串,Eloquent会自动将其转换为PostgreSQL支持的时间格式,避免手动转换可能带来的格式错误或引号问题。
这样修改后,你的查询就能正常执行,不会再触发"列不存在"的错误了。
内容的提问来源于stack exchange,提问作者Aleksej_Shherbak
相关产品推荐
相关产品推荐

