Back to Tools

SQL Syntax Error — 10 Most Common Mistakes and Fixes

MySQL, PostgreSQL, and SQLite syntax errors explained and fixed

SQL syntax errors stop your query before it runs. The database engine tells you near what the error occurred, but figuring out why can be tricky. This guide covers the 10 most common SQL syntax mistakes with a broken example and a working fix for each.

Error 1: Missing Single Quotes Around Strings

String values in SQL must be wrapped in single quotes. Without them, the parser treats the value as a column or table name and raises a syntax error.

Broken:

SELECT * FROM users WHERE name = John;
-- ERROR: column "john" does not exist

Fixed:

SELECT * FROM users WHERE name = 'John';

Error 2: Using Reserved Words as Column/Table Names

Words like order,group,select, and desc are SQL keywords. Using them as column names causes syntax errors.

Broken:

SELECT id, order, status FROM shipments;
-- ERROR: syntax error near 'order'

Fixed — MySQL (backticks), PostgreSQL/SQLite (double quotes):

-- MySQL
SELECT id, `order`, status FROM shipments;

-- PostgreSQL / SQLite
SELECT id, "order", status FROM shipments;

Error 3: Trailing Comma in SELECT

An extra comma before FROM is one of the most common typos. The parser sees a comma and expects another column name, but finds a keyword instead.

Broken:

SELECT id, name, email, FROM users;
-- ERROR: syntax error near 'FROM'

Fixed:

SELECT id, name, email FROM users;

Error 4: Missing Comma Between Columns

Forgetting a comma between column names in SELECT is often misread as an alias assignment, leading to confusing errors.

Broken:

SELECT id name email FROM users;
-- MySQL: treats 'name' as alias for id, then fails on 'email'

Fixed:

SELECT id, name, email FROM users;

Error 5: WHERE vs HAVING Confusion

WHERE filters rows before grouping.HAVING filters groups after aggregation. Aggregate functions like COUNT(),SUM() must use HAVING.

Broken:

SELECT department, COUNT(*) as total
FROM employees
GROUP BY department
WHERE COUNT(*) > 5;
-- ERROR: Invalid use of group function

Fixed:

SELECT department, COUNT(*) AS total
FROM employees
GROUP BY department
HAVING COUNT(*) > 5;

Error 6: JOIN ON Clause Issues

A JOIN missing its ON condition, using the wrong alias, or referencing a non-existent column will fail with a syntax or reference error.

Broken:

SELECT u.name, o.total
FROM users u
JOIN orders o ON users.id = o.user_id;
-- ERROR: unknown table 'users' in ON clause (alias 'u' not used)

Fixed — use the alias consistently:

SELECT u.name, o.total
FROM users u
JOIN orders o ON u.id = o.user_id;

Error 7: Subquery Not Aliased

Most SQL databases require every derived table (subquery in FROM) to have an alias. Omitting it causes a syntax error.

Broken:

SELECT * FROM (
  SELECT id, name FROM users WHERE active = 1
);
-- ERROR: Every derived table must have its own alias

Fixed:

SELECT * FROM (
  SELECT id, name FROM users WHERE active = 1
) AS active_users;

Error 8: Wrong ORDER BY with GROUP BY

In strict SQL mode, you can only ORDER BY columns that are in GROUP BY or are aggregate functions. Non-aggregated columns cause an error.

Broken (PostgreSQL / strict MySQL):

SELECT department, COUNT(*) AS total
FROM employees
GROUP BY department
ORDER BY name;  -- 'name' is not in GROUP BY or aggregate
-- ERROR: column "name" must appear in GROUP BY or be used in aggregate

Fixed:

SELECT department, COUNT(*) AS total
FROM employees
GROUP BY department
ORDER BY total DESC;  -- aggregate function: OK
-- or
ORDER BY department;  -- in GROUP BY: OK

Error 9: NULL Comparison — = NULL vs IS NULL

NULL is not equal to anything — not even itself. = NULL always returns unknown (no rows matched), not a syntax error, but logically wrong. UseIS NULL orIS NOT NULL.

Broken — returns 0 rows, silently wrong:

SELECT * FROM users WHERE deleted_at = NULL;
-- Returns 0 rows — = NULL is always UNKNOWN

Fixed:

SELECT * FROM users WHERE deleted_at IS NULL;
SELECT * FROM users WHERE deleted_at IS NOT NULL;

Error 10: Single Quote Inside String — Not Escaped

An apostrophe inside a string value ends the string early, causing a syntax error. Escape it by doubling the single quote or use a parameterized query.

Broken:

SELECT * FROM users WHERE name = 'O'Brien';
-- ERROR: syntax error near 'Brien'

Fixed — escape with double single-quote or use parameters:

-- Escape the apostrophe
SELECT * FROM users WHERE name = 'O''Brien';

-- Best practice: use parameterized queries (Python example)
cursor.execute("SELECT * FROM users WHERE name = %s", ("O'Brien",))

SQL Syntax Checklist

  • 1All string values are wrapped in single quotes
  • 2No trailing comma before FROM, WHERE, or other keywords
  • 3All columns in SELECT are separated by commas
  • 4Reserved words used as identifiers are escaped (backticks or double quotes)
  • 5Aggregate functions (COUNT, SUM) are in HAVING, not WHERE
  • 6Every JOIN has an ON clause using the correct alias
  • 7Every subquery in FROM has an alias (AS sub_name)
  • 8NULL checks use IS NULL / IS NOT NULL, not = NULL

Format your SQL query for readability

A properly formatted query makes syntax errors immediately visible.

Format your SQL query for readability →

Frequently Asked Questions

What does 'syntax error near' mean in SQL?

It means the parser encountered an unexpected token at that position. The error shows what was found, not necessarily what is wrong — look at what comes immediately before it for the actual mistake (missing comma, missing quote, reserved word).

How do I fix a reserved word conflict in SQL?

Wrap the reserved word in backticks for MySQL (`order`) or double quotes for PostgreSQL/SQLite ("order"). Renaming the column to avoid the conflict is the best long-term solution.

Why does my SQL string comparison fail?

String values must use single quotes: WHERE name = 'Alice'. Double quotes are for identifiers (column/table names) in most SQL dialects.

How do I debug a SQL syntax error?

Format the query, read the error token, then work backward. Reduce the query to its simplest form and add clauses back one at a time until the error reappears — that clause contains the problem.

What's the difference between WHERE and HAVING?

WHERE filters individual rows before grouping and cannot reference aggregate functions. HAVING filters groups after GROUP BY and can use aggregates. If you seeCOUNT(*) > 5 in your filter, it belongs in HAVING.

Related Developer Tools