Fix: MySQL ERROR 1064 (42000): You have an error in your SQL syntax
Part of: Database Errors
Quick Answer
How to fix MySQL syntax error 1064 caused by typos, reserved words, wrong quotes, missing commas, version-incompatible syntax, and ORM-generated queries.
The Parser Stopped Cold
Personally, I treat MySQL ERROR 1064 as one of the most informative error messages MySQL produces, once you know how to read it. The near '...' quote names roughly where the parser quit, and the actual mistake is almost always a few tokens before that point. I have lost very few hours to this error since I learned to read it backwards. You run a MySQL query and get:
ERROR 1064 (42000): You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version
for the right syntax to use near 'order VALUES (1, "test")' at line 1Or variations:
ERROR 1064 (42000): You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version
for the right syntax to use near 'LIMIT 10' at line 3#1064 - You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version
for the right syntax to use near '' at line 1MySQL’s parser could not understand your SQL statement. The near '...' part tells you approximately where the syntax error is; look at the text shown and the few characters before it.
The “(42000)” portion is the SQLSTATE code for “syntax error or access rule violation.” It is generic across SQL databases, but error number 1064 is MySQL-specific and always means the same thing: the parser rejected the statement before it could even attempt to run.
Quick Reference Before You Dive In
If you arrived here from Google with a fresh ERROR 1064, the five facts that resolve roughly 90 percent of cases:
- The position in the error is where the parser GAVE UP, not where the mistake was made. Read the few tokens BEFORE the
near '...'quote. The MySQL keywords and reserved words list is the canonical reference for the most common cause. - The single most common cause is a reserved word used as a column or table name.
order,group,status,name,user,rank,key,indexare all reserved. Wrap identifiers in backticks:SELECT `order` FROM `user`. - Use BACKTICKS (
`) for identifiers, single quotes (') for strings. Double quotes work for strings in defaultsql_mode, but break inANSI_QUOTESmode and conflict with identifiers. Backticks always identify, single quotes always quote strings. - MySQL version matters. Window functions (8.0+), CTEs (8.0+),
CHECKconstraints (8.0.16+) all require modern MySQL. RunSELECT VERSION();first if you copy-pasted modern SQL into a server you do not know. - The error always fires BEFORE the statement runs. It cannot corrupt data. The fix is always editorial; you just need to find the token the parser tripped on.
The rest of this article walks through each cause in detail, plus the failure modes most other guides skip.
How the MySQL Parser Actually Fails
MySQL’s SQL parser follows strict grammar rules generated from a formal grammar file (sql_yacc.yy). When the parser reaches a token it cannot fit into the grammar (a missing keyword, a reserved word used as an identifier, a wrong quote character, or a leftover comma) it stops, throws away the rest of the statement, and reports error 1064.
The most important thing to understand about this error: the position in the error message is where the parser gave up, not where the mistake was made. Parsers read left to right; by the time MySQL realizes something is wrong, it has already consumed several tokens past the real problem. Always look at the few tokens before the near '...' quote.
A second non-obvious cause is that the parser does not have access to your schema when it parses the statement; it does not yet know which words are table names or column names. That is why a typo like SELET * FROM users is reported as a syntax error rather than as a “command not found.” The parser cannot distinguish between an unknown keyword and an unknown identifier until much later in the pipeline.
Common causes, ordered roughly by frequency:
- Reserved word used as a column or table name.
order,group,select,table,key,index,status,name,user,rank,condition,system,current_user. - Wrong quote characters. Using double quotes (
") instead of backticks (`) for identifiers, or smart quotes pasted from a word processor. - Missing comma between column definitions or values, or conversely a trailing comma where one is not allowed.
- Typo in a SQL keyword.
INSER INTOinstead ofINSERT INTO,WEREinstead ofWHERE. - MySQL version mismatch. Using syntax that is not available in your MySQL version: window functions, CTEs, and
CHECKconstraints all have version requirements. - Copy-paste from other databases. PostgreSQL
SERIAL/JSONB, SQL ServerIDENTITY/TOP, or SQLiteAUTOINCREMENTquirks are not valid MySQL. - ORM-generated queries against the wrong dialect. Prisma, Sequelize, SQLAlchemy, or Django ORM configured for the wrong database, or a hand-written
.raw()query that mixes dialects.
The good news: error 1064 always happens before the statement runs, so it cannot corrupt data or leave the database in an inconsistent state. The fix is always editorial; find the token the parser tripped on and adjust the SQL.
When to Use Which Fix
The next sections cover the fixes in detail. The table below maps your symptom to the recommended fix.
| Your symptom | Recommended fix | Why |
|---|---|---|
near 'order', near 'group', near 'status' etc. | Fix 1: backtick the reserved word | Most common cause |
near '"...' or smart quotes from word processor | Fix 2: use backticks for IDs, single quotes for strings | Wrong quote character |
near ',' or extra trailing comma | Fix 3: check column / values list for trailing commas | Easy to miss in long lists |
near 'SELET', near 'WERE' | Fix 4: typo in SQL keyword | Look at the bad token |
| Window function or CTE rejected | Fix 5: check MySQL version (8.0+ needed) | Older versions miss features |
| Copy-pasted from Postgres / SQL Server / SQLite | Fix 6: translate dialect-specific syntax | Each engine differs |
| ORM-generated query failing | Fix 7: check dialect config; log raw SQL | Wrong dialect or mixed quoting |
near 'LIMIT', near 'OFFSET' after UNION | Fix 8: wrap each UNION arm in parens or move to outer query | Operator precedence |
If multiple rows apply, pick the topmost one.
Fix 1: Escape Reserved Words with Backticks
The most common cause of error 1064. MySQL has many reserved words that cannot be used as identifiers without escaping:
Broken:
CREATE TABLE order (
id INT PRIMARY KEY,
status VARCHAR(50)
);
-- ERROR 1064: near 'order' — 'order' is a reserved wordFixed — use backticks:
CREATE TABLE `order` (
id INT PRIMARY KEY,
`status` VARCHAR(50)
);Common reserved words that trip people up:
| Word | Alias fix |
|---|---|
order | orders, `order` |
group | groups, `group` |
table | tables, `table` |
key | `key` |
index | `index` |
status | `status` |
user | users, `user` |
name | `name` |
select | `select` |
values | `values` |
rank | `rank` |
condition | `condition` |
A naming habit I have adopted over the years: avoid reserved words for column and table names entirely. Use plural nouns for tables (orders, users) and descriptive prefixes for columns (order_status, user_name). Backticks fix the immediate parse error, but the moment you forget one in a JOIN expression you are back here debugging again. Names that are not reserved survive every dialect.
Fix 2: Use Correct Quote Characters
MySQL uses three types of quotes, each for a different purpose:
| Character | Purpose | Example |
|---|---|---|
Backtick ` | Identifiers (tables, columns) | `order` |
Single quote ' | String values | 'hello' |
Double quote " | String values (by default) or identifiers (with ANSI_QUOTES mode) | "hello" |
Broken — double quotes for identifiers (not standard MySQL):
SELECT "name" FROM "users";
-- MySQL treats "name" as a string literal, not a column nameFixed — backticks for identifiers:
SELECT `name` FROM `users`;Broken — backticks for values:
INSERT INTO users (name) VALUES (`Alice`);
-- ERROR: `Alice` is treated as a column name, not a stringFixed — single quotes for values:
INSERT INTO users (name) VALUES ('Alice');Broken — smart quotes from word processors:
SELECT * FROM users WHERE name = 'Alice'; -- Smart quotes!Fixed — straight single quotes:
SELECT * FROM users WHERE name = 'Alice';Copy-pasting SQL from Word, Google Docs, Slack, or Notion often introduces smart quotes. Always type quotes directly in your SQL editor.
Fix 3: Fix Missing Commas and Parentheses
Missing comma between columns:
CREATE TABLE users (
id INT PRIMARY KEY
name VARCHAR(100) -- Missing comma after PRIMARY KEY!
email VARCHAR(200)
);Fixed:
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(100),
email VARCHAR(200)
);Missing closing parenthesis:
INSERT INTO users (name, email VALUES ('Alice', 'alice@example.com');
-- Missing ) after emailFixed:
INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com');Extra comma at the end:
SELECT name, email, FROM users;
-- Extra comma before FROMFixed:
SELECT name, email FROM users;An adjacent foot-gun that catches developers coming from JavaScript or Python: trailing commas. [1, 2, 3,] is valid JS but INSERT INTO t (a, b, c,) VALUES (1, 2, 3,) is not valid SQL. The parser tolerates none of them. When ERROR 1064 quotes a near ')' or near ',', the trailing-comma trap is the first thing I check.
Fix 4: Fix Version-Specific Syntax
Some SQL features are only available in certain MySQL versions:
Window functions (MySQL 8.0+):
SELECT name, ROW_NUMBER() OVER (ORDER BY created_at) as row_num
FROM users;
-- ERROR 1064 on MySQL 5.7 — window functions not supportedCommon Table Expressions / CTE (MySQL 8.0+):
WITH active_users AS (
SELECT * FROM users WHERE active = 1
)
SELECT * FROM active_users;
-- ERROR 1064 on MySQL 5.7CHECK constraints (MySQL 8.0.16+):
CREATE TABLE products (
price DECIMAL(10,2) CHECK (price > 0)
);
-- Silently ignored before MySQL 8.0.16Check your MySQL version:
SELECT VERSION();If you are on MySQL 5.7 and need these features, either upgrade to MySQL 8.0 or rewrite the query using supported syntax.
Fix 5: Fix INSERT and UPDATE Syntax
Missing VALUES keyword:
INSERT INTO users (name, email) ('Alice', 'alice@example.com');
-- Missing VALUESFixed:
INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com');SET syntax for UPDATE:
UPDATE users SET name = 'Alice', WHERE id = 1;
-- Extra comma before WHEREFixed:
UPDATE users SET name = 'Alice' WHERE id = 1;Wrong multi-row INSERT:
INSERT INTO users (name) VALUES ('Alice'), ('Bob'), ('Charlie',);
-- Trailing comma after last rowFixed:
INSERT INTO users (name) VALUES ('Alice'), ('Bob'), ('Charlie');If the INSERT succeeds but violates a constraint, see Fix: PostgreSQL duplicate key violates unique constraint (the concept is similar for MySQL unique key violations).
Fix 6: Fix Escaped Characters in Strings
Unescaped single quote in a string:
INSERT INTO posts (title) VALUES ('It's a test');
-- ERROR: the parser sees 'It' as the string, then 's a test' is unexpectedFixed — escape with backslash:
INSERT INTO posts (title) VALUES ('It\'s a test');Fixed — double the single quote:
INSERT INTO posts (title) VALUES ('It''s a test');Fixed — use prepared statements (best for application code):
cursor.execute("INSERT INTO posts (title) VALUES (%s)", ("It's a test",))Prepared statements handle escaping automatically and prevent SQL injection. For related security best practices, see Fix: MySQL access denied for user.
Fix 7: Fix ORM-Generated SQL
When an ORM generates the failing query, the cause is usually one of three things: a .raw() call with a hand-written fragment, a misconfigured dialect, or a feature only available in newer MySQL versions than your server runs.
Check what SQL the ORM actually produced. Most ORMs have a way to log the generated statement:
# SQLAlchemy
engine = create_engine("mysql://...", echo=True)
# Django
import logging
logging.getLogger('django.db.backends').setLevel(logging.DEBUG)// Prisma
new PrismaClient({ log: ['query'] });
// TypeORM
new DataSource({ logging: ['query'] });Once you see the generated query, error 1064 becomes a regular SQL syntax problem and the earlier fixes apply.
Check that the ORM’s dialect matches the server. If you wired up Sequelize with dialect: 'postgres' but point it at a MySQL server, it will happily generate RETURNING * clauses, JSONB types, and SERIAL columns — all of which are 1064 errors in MySQL.
Check the MySQL version the ORM targets. Some Prisma features (full-text search modes, certain JSON paths) generate MySQL 8.0+ syntax. Running against MySQL 5.7 produces 1064 even though the migration file looked fine.
Real-world scenario: A common 1064 with Django ORM appears when you write .extra(select={'foo': 'CASE WHEN ... END'}) and forget to alias subqueries. Django ORM forwards the fragment unchanged. Reproduce by enabling query logging, copy the failing SQL into the mysql CLI, and the actual position of the error becomes clear.
Fix 8: Fix Imported or Generated SQL
If the error comes from a SQL dump or migration file:
Check the file encoding. UTF-8 BOM or other encoding issues can cause invisible characters:
file dump.sql
# Should show: ASCII text or UTF-8 Unicode textCheck for database-specific syntax. If the dump came from PostgreSQL or SQL Server:
-- PostgreSQL syntax (not valid in MySQL):
CREATE TABLE users (
id SERIAL PRIMARY KEY, -- MySQL uses AUTO_INCREMENT
data JSONB -- MySQL uses JSON (no JSONB)
);
-- MySQL equivalent:
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
data JSON
);Check for delimiter issues in stored procedures:
DELIMITER //
CREATE PROCEDURE my_proc()
BEGIN
SELECT 1;
END //
DELIMITER ;Without the DELIMITER change, the ; inside the procedure body terminates the statement prematurely.
Fix 9: Debug the Error Location
The near '...' text in the error message shows where the parser stopped. The actual error is usually just before that text:
ERROR 1064: ... for the right syntax to use near 'FROM users' at line 2This means the error is just before FROM — check the column list or expression before FROM.
Tips for finding the error:
- Read the
near '...'text. - Look at the few words before that text in your query.
- Check for missing commas, parentheses, or keywords at that point.
- If
near ''(empty string), the error is at the very end of the statement — usually a missing closing parenthesis or semicolon.
Break the query into parts to isolate the error:
-- Start with the simplest version:
SELECT * FROM users;
-- Add clauses one by one:
SELECT * FROM users WHERE active = 1;
SELECT * FROM users WHERE active = 1 ORDER BY name;
SELECT * FROM users WHERE active = 1 ORDER BY name LIMIT 10;The first version that fails tells you which clause has the error.
Stranger Causes I Have Tracked Down
Check for invisible characters. Copy-pasting SQL from web pages can introduce zero-width spaces or non-breaking spaces:
cat -A query.sql | head -5Look for unexpected M-BM- or ^M characters.
Check the SQL mode. MySQL’s sql_mode setting affects what syntax is valid:
SELECT @@sql_mode;ANSI_QUOTES mode makes double quotes work as identifier quotes (like PostgreSQL). NO_BACKSLASH_ESCAPES disables backslash escaping.
Check for client-specific issues. Some MySQL clients (phpMyAdmin, MySQL Workbench, DBeaver) add their own delimiters or modify queries. Try running the query directly in the mysql command-line client.
Use an SQL formatter. Paste your query into an SQL formatter to highlight structural issues. Mismatched parentheses and missing keywords become obvious with proper formatting.
What Other Tutorials Get Wrong About ERROR 1064
Most MySQL tutorials list the same fixes but frame them in ways that produce subtle bugs.
They show the error position as the location of the mistake. The parser stops one or more tokens AFTER the real problem. Tutorials that say “look at where the error happened” send readers staring at correct SQL. Always look at the tokens BEFORE the near '...' quote.
They confuse backticks with single quotes. Backticks (`) quote identifiers (column / table names). Single quotes (') quote string literals. Tutorials that recommend “use quotes” without specifying which produce code that crashes in a different way.
They omit the SQL mode wrinkle. ANSI_QUOTES makes double quotes work as identifier quotes. If your local server has it enabled and production does not, the same code passes locally and fails in deployment. Articles that present quoting rules without mentioning sql_mode miss this trap.
They miss version-specific syntax errors. Window functions, CTEs, JSON_TABLE, and CHECK constraints require MySQL 8.0+. Articles that show modern SQL without flagging the version requirement send users on MariaDB 10.1 or MySQL 5.7 chasing phantom syntax bugs.
They omit the ORM dialect-mismatch case. Prisma, Sequelize, SQLAlchemy, Django ORM can all produce SQL for the wrong dialect if misconfigured. Tutorials focused on hand-written SQL miss that the bug is in the framework configuration, not in any specific query.
They miss invisible-character traps. Smart quotes from word processors, BOM bytes from UTF-8 files saved by certain editors, and trailing CR characters from Windows line endings all produce ERROR 1064 with confusing near '...' quotes. cat -A reveals these instantly; tutorials that focus only on visible characters leave readers scratching their heads.
Frequently Asked Questions
Why is the position in the error message wrong?
The error position is where the parser GAVE UP, not where the mistake was made. Parsers read left-to-right and consume tokens until the grammar fails. The actual bad token is usually one or two earlier. Always inspect the tokens before the near '...' quote.
What is the difference between backticks and single quotes?
Backticks (`) quote identifiers: column names, table names, database names. Single quotes (') quote string literals. They are not interchangeable. Use backticks when you need to use a reserved word as a column name (`order`); use single quotes for string values (WHERE name = 'Alice').
Why does my query work in phpMyAdmin but fail in code?
Three common causes. First, the client library uses a different default sql_mode than the GUI. Second, the GUI strips trailing semicolons but the library does not (the library may need exactly one statement, GUI accepts many). Third, ORM frameworks add their own quoting that interacts badly with hand-written fragments. Log the actual SQL the library sends and compare.
Is ERROR 1064 ever a sign of data corruption?
No. The parser fails before the statement runs. The database state is untouched. Error 1064 is always editorial; you just need to fix the SQL syntax.
Why does the same query work in MySQL 8 but fail in MySQL 5.7?
MySQL 8.0 added many SQL features: window functions, CTEs, JSON_TABLE, CHECK constraints (8.0.16+), regular expressions improvements, lateral joins. MySQL 5.7 lacks these. Run SELECT VERSION(); to confirm; either upgrade the server or rewrite the query without modern features.
Why does my ORM produce queries that error 1064?
Common causes: the ORM is configured for the wrong dialect (Postgres SQL aimed at MySQL), the model uses a column name that is a reserved word and the ORM does not auto-quote, or you concatenated raw SQL fragments that mixed quoting styles. Enable query logging and inspect the exact SQL the ORM sends.
If the table itself does not exist rather than having a syntax error, see Fix: MySQL table doesn’t exist.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: MySQL Full-Text Search Not Working — MATCH AGAINST Returns No Results
How to fix MySQL full-text search issues — FULLTEXT index creation, minimum word length, stopwords, boolean mode vs natural language mode, InnoDB vs MyISAM, and LIKE fallback.
Fix: MySQL Deadlock Found When Trying to Get Lock
How to fix MySQL 'Deadlock found when trying to get lock; try restarting transaction' — diagnosing deadlock causes, using SHOW ENGINE INNODB STATUS, and preventing deadlocks with consistent lock ordering.
Fix: MySQL ERROR 1146 (42S02): Table 'database.table' doesn't exist
How to fix MySQL error 1146 Table doesn't exist caused by wrong database selection, case sensitivity issues, missing migrations, InnoDB tablespace corruption, and cross-OS imports.
Fix: ClickHouse Not Working — MergeTree ORDER BY, INSERT Batching, LowCardinality, and Replication
How to fix ClickHouse errors — table engine choice, ORDER BY for primary key, INSERT too many small parts, LowCardinality types, Nullable performance, ZooKeeper for Replicated tables, and HTTP vs Native client.