Skip to content
ohsudo, Home
Databases

MySQL "ERROR 1064: You have an error in your SQL syntax": how to read it and fix it

Fix MySQL ERROR 1064: read the "near" text, then check reserved words like rank and groups, quotes, commas, old GRANT syntax and queries written for another database.

Beginner4 min readApplies to MySQL 8.0 · MySQL 8.4 LTS · MariaDB 10.6+

by OhSudo ·

Checked on real software: MySQL 8.4 · November 2026How we check

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 'FROM players' at line 1

MySQL couldn’t parse your statement. The message looks vague, but the useful part is the end: near '…' starts at the point where the parser gave up. The mistake is usually right there, or just before it.

This came from SELECT rank FROM players. FROM is fine: the mistake is rank, the word just before it, because since MySQL 8.0 it’s a reserved word.

TL;DR

Read what comes after near, then look at the word just before it:

  • near '' at the end: the statement stops too early, usually a missing ) or '.
  • The word before it is a column or table name: probably a reserved word. Quote it with backticks: `rank`.
  • A word right after a list: a missing or extra comma.
  • Copied from elsewhere: syntax from another database, or from an older MySQL.
SELECT VERSION(); -- rules change between versions

1. Reserved words used as names

MySQL 8.0 added new reserved words, so a query that worked for years can break after an upgrade. Common ones: rank, groups, row, rows, system, function, lead, lag, window, over, recursive. Older ones are order, group, key, index, desc, from, to.

SELECT rank FROM players; -- ERROR 1064
SELECT `rank` FROM players; -- works

Backticks work in every statement. To avoid the problem altogether, choose names that aren’t reserved words (player_rank), and have your ORM quote identifiers.

2. Quotes

MySQL has three kinds, and they aren’t interchangeable:

Quote Means
'text' A string
`name` A table or column name
"text" A string by default; a name with ANSI_QUOTES mode on

Two classic mistakes, an apostrophe inside a string and “smart” quotes pasted from a document:

INSERT INTO notes (body) VALUES ('it's broken'); -- ERROR 1064, the string ends at it'
INSERT INTO notes (body) VALUES ('it''s fine'); -- works

‘text’ with curly quotes also gives ERROR 1064: retype them. In application code, never build SQL by joining strings: use parameters. It avoids this error, and SQL injection too.

3. Commas and brackets

SELECT id, name, FROM users; -- comma before FROM
SELECT id name email FROM users; -- missing comma: "name" is read as an alias
CREATE TABLE t (id INT, name TEXT,); -- comma before )

The second one is a good example of the rule: id name is valid (an alias), so MySQL only complains at email, one word later than the real mistake.

The empty near '' means the statement ended while MySQL still expected something:

ERROR 1064 (42000): … near '' at line 1

Look for a missing ) or a closing quote.

4. Syntax from another database

Each database has its own dialect. These are the usual travellers:

Wrong in MySQL From In MySQL
SELECT TOP 5 * FROM t SQL Server SELECT * FROM t LIMIT 5
WHERE name ILIKE 'a%' PostgreSQL WHERE name LIKE 'a%' (case-insensitive by default collation)
SELECT price::int PostgreSQL SELECT CAST(price AS SIGNED)
INSERT … RETURNING id PostgreSQL SELECT LAST_INSERT_ID() (MariaDB does support RETURNING)
[name] SQL Server `name`

The SQL Dialect Reference shows the same statement in MySQL, MariaDB, PostgreSQL, SQL Server, Oracle and SQLite, side by side.

5. Syntax from an older MySQL

Tutorials and scripts from years ago often use syntax that has since been removed. The most common by far is creating a user inside GRANT, which MySQL 8.0 no longer accepts:

-- ERROR 1064 on MySQL 8.0 and later
GRANT ALL PRIVILEGES ON shop.* TO 'app'@'%' IDENTIFIED BY 'secret';

Do it in two steps:

CREATE USER 'app'@'%' IDENTIFIED BY 'a-long-password';
GRANT ALL PRIVILEGES ON shop.* TO 'app'@'%';

Also from old dumps: TYPE=InnoDB instead of ENGINE=InnoDB. MariaDB still accepts some of what MySQL has removed, including GRANT … IDENTIFIED BY, so a script can work on one and fail on the other.

6. Procedures and triggers need DELIMITER

In the mysql client, each ; ends the statement, including the ones inside a procedure’s body, so MySQL sees half a procedure:

DELIMITER //
CREATE PROCEDURE add_one(IN x INT)
BEGIN
SELECT x + 1;
END //
DELIMITER ;

DELIMITER is a command of the client, not SQL. Don’t send it from application code.

Shell, we have a problem!

Similar, but different: ERROR 1054 (42S22): Unknown column and ERROR 1146 (42S02): Table doesn't exist mean the syntax is right, and the name isn’t. ERROR 1045: Access denied is about your login: see MySQL ERROR 1045. A refused emoji is a different error: see Incorrect string value. To practice writing queries, try the SQL Exercises, which run on PostgreSQL and SQLite. ERROR 1452 means the statement is valid, and a foreign key rejects its data.

Found this useful? Share it.

Found a mistake? Let us know at contact@ohsudo.com.

Tools

Try it yourself

Articles

Related articles