The laravel unknown column ‘CONCAT’ error appears the moment you try to use a SQL function like CONCAT() directly inside ->select(). Laravel’s query builder escapes every string argument as an identifier by default, so your SQL expression gets wrapped in backticks and shipped to MySQL as a column name that obviously doesn’t exist. The fix is to tell Eloquent “this is raw SQL, don’t touch it” — via DB::raw() or selectRaw(). This guide covers both, when to pick which, and the accessor-vs-SQL trade-off that comes up next.
Last verified: 2026-04-23 on Laravel 11 with PHP 8.3 and MySQL 8.0. Originally published 2022-11-06, rewritten and updated 2026-04-23.
TL;DR
Wrap the SQL expression in DB::raw() — or switch the call to selectRaw(). Both stop Laravel from escaping the expression as a column name, which is what produces the “Unknown column ‘CONCAT…'” error.
Why the error happens
When you pass strings to ->select(), the query builder treats each one as a column identifier. It wraps them in backticks (MySQL) or double quotes (PostgreSQL), which is what keeps reserved words and mixed-case column names working. But that same escaping turns an unescaped SQL expression into a single malformed identifier:
// Eloquent call
User::where('id', '=', 10)
->select(
'id',
"CONCAT(first_name, ' ', last_name) as full_name",
'username',
'email',
)
->get();
// The SQL Laravel actually sends
select `id`, `CONCAT(first_name, ' ', last_name) as full_name`, `username`, `email`
from `users` where `id` = ?;
MySQL parses those backticks, looks for a column literally named CONCAT(first_name, ' ', last_name) as full_name, doesn’t find one, and raises:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'CONCAT(first_name, ...) as full_name' in 'field list'
Fix 1 — Wrap in DB::raw()
The minimal change: import the DB facade and wrap the raw expression. Everything else in the select() list stays normal.
use Illuminate\Support\Facades\DB;
User::where('id', '=', 10)
->select(
'id',
DB::raw("CONCAT(first_name, ' ', last_name) as full_name"),
'username',
'email',
)
->get();
Laravel now sees the DB::raw expression instance, knows not to escape it, and interpolates the SQL verbatim. MySQL runs CONCAT() like you’d expect, and full_name comes back as a real attribute on each returned model.

Fix 2 — selectRaw()
If every column in your select list is a raw expression, selectRaw() is less noisy — one call, one string, optional bindings:
User::where('id', '=', 10)
->selectRaw(
"id, CONCAT(first_name, ' ', last_name) as full_name, username, email"
)
->get();
The whole string is treated as raw SQL, so the non-expression columns (id, username, email) are also emitted unescaped. That’s fine for columns you control — risky for anything user-supplied. The rule below applies to both forms.
Safety — never interpolate user input into a raw expression
Anything inside DB::raw() or selectRaw() bypasses Laravel’s parameter binding, which means it bypasses SQL-injection protection too. Never concatenate request input into the raw string:
// NEVER do this — $request->separator is attacker-controlled
DB::raw("CONCAT(first_name, '{$request->separator}', last_name)")
// Safe — pass dynamic values via bindings
User::selectRaw(
"CONCAT(first_name, ?, last_name) as full_name",
[$request->separator]
)->get();
Both selectRaw() and the ->where('...', [bindings]) variants accept an array of bindings as the second argument. Use those for anything dynamic; keep literal SQL reserved for column names and function calls you fully control.
Alternative — compute in PHP with an accessor
If you only need full_name for display and not for filtering or ordering, skip the SQL concatenation entirely and define an Eloquent accessor:
// app/Models/User.php
use Illuminate\Database\Eloquent\Casts\Attribute;
protected function fullName(): Attribute
{
return Attribute::get(fn () => trim("{$this->first_name} {$this->last_name}"));
}
Now $user->full_name works on every model instance without changing any query. Reach for the SQL CONCAT approach when you need to ORDER BY full_name, WHERE full_name LIKE ?, or GROUP BY a concatenated value — cases the accessor can’t handle because the value doesn’t exist in the database.
Frequently asked questions
CONCAT as a laravel unknown column? Because ->select() escapes every string argument as an identifier (a column or table name). Eloquent wraps "CONCAT(first_name, ' ', last_name)" in backticks and sends it to MySQL as `CONCAT(first_name, ' ', last_name)` — a single weirdly-named column that doesn’t exist. Wrap the expression in DB::raw() or switch the call to selectRaw() so Eloquent knows not to escape it.
DB::raw vs selectRaw — which should I use? They produce the same SQL. selectRaw() is a convenience: one call, one string, optional bindings. DB::raw() is better when you want to mix raw and escaped columns in a single select(). Rule of thumb: all-raw → selectRaw; mixed → select(['id', 'email', DB::raw('...')]).
select() safe from SQL injection? Raw expressions are injected verbatim — anything inside DB::raw() or selectRaw() bypasses Laravel’s parameter binding. Never interpolate user input into the raw string. If you need a dynamic value, pass it via bindings: selectRaw('CONCAT(first_name, ?, last_name) as full_name', [' ']). Literal SQL keywords and column names you control are fine.
CONCAT_WS or other MySQL functions the same way? Yes. Any SQL expression goes inside DB::raw(): DB::raw("CONCAT_WS(' ', first_name, middle_name, last_name) as full_name"), DB::raw('UPPER(email) as email_upper'), DB::raw('DATE(created_at) as created_date'). Laravel doesn’t care what function you use — it just stops escaping the string as a column name.
It depends on what you do with the value. If you’re only displaying it, concatenate in PHP (an Eloquent accessor is the standard home for this): public function getFullNameAttribute() { return "{$this->first_name} {$this->last_name}"; }. Do it in SQL when you need to ORDER BY, WHERE, or GROUP BY the concatenated value, or when you’re streaming results and want to avoid the per-row PHP cost.
Related guides
- How to Use Multiple where and orWhere in Laravel Eloquent — combining raw expressions with bound conditions.
- How to Use Order By in Eloquent Laravel — ordering by a computed column like the one CONCAT produces.
- How to Do a Left Outer Join with Laravel — another case where raw SELECT lists come up.
- How to Install Laravel on Ubuntu — Laravel 11 setup before you touch Eloquent.
References
Official Laravel query-builder docs (DB::raw, selectRaw, raw expressions): laravel.com/docs/queries. MySQL CONCAT reference: dev.mysql.com/doc/refman/8.0.