Fix ORA-00933: SQL command not properly ended in Oracle
This error fires when Oracle's parser hits a token it wasn't expecting. Usually a misplaced JOIN or stray comma. Here's why and how to fix it.
You're running a SQL query in Oracle (through SQL*Plus, SQL Developer, or some app), and you get ORA-00933: SQL command not properly ended. This usually happens when you've written something like SELECT * FROM t1, t2 WHERE t1.id = t2.id JOIN t3 ON ... — mixing old-style comma joins with modern ANSI JOIN syntax. Or you forgot a keyword. Or you have a trailing comma in your SELECT list. The error can also appear in Oracle Forms or Reports when a query string gets concatenated wrong.
What's actually happening here
Oracle's SQL parser reads tokens left to right. When it hits a token that doesn't fit the grammar rules at that point, it throws ORA-00933. The parser is strict — it doesn't try to guess what you meant. The message "not properly ended" is misleading; it really means "I hit something I can't make sense of right now."
Common triggers and root causes
- Mixing old and new JOIN syntax — This is the #1 cause. You can't write
FROM t1, t2 JOIN t3 ON .... Oracle sees the comma before JOIN and gets confused. - Trailing comma in SELECT —
SELECT col1, col2, FROM t1. The comma after col2 is illegal. - Missing keyword — Like
SELECT col1 FROM t1 WHERE col2 = SELECT max(col2) FROM t2— you need parentheses around the subquery:WHERE col2 = (SELECT ...). - Wrong keyword order — Oracle expects
SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY. Out of order confuses the parser. - Extra characters at end — A stray semicolon inside PL/SQL, or a trailing comma in INSERT column list.
The fix
- Identify the exact query — If it's in a program, log the exact SQL string that caused the error. Don't guess — print the query.
- Check for mixed JOIN syntax — Look for a comma after FROM before a JOIN keyword. Example of broken query:
Fix: Use all ANSI JOIN syntax:SELECT * FROM employees e, departments d WHERE e.dept_id = d.dept_id JOIN locations l ON d.loc_id = l.loc_id;
Or use all comma-style (but old-style is harder to maintain with more tables):SELECT * FROM employees e JOIN departments d ON e.dept_id = d.dept_id JOIN locations l ON d.loc_id = l.loc_id;SELECT * FROM employees e, departments d, locations l WHERE e.dept_id = d.dept_id AND d.loc_id = l.loc_id; - Remove trailing commas — Scan SELECT column list, INSERT column list, and VALUES clause. Every line except the last must have a comma, but none after the last.
- Add missing parentheses — Subqueries in WHERE, HAVING, or FROM need parentheses:
-- Wrong SELECT * FROM t1 WHERE id IN SELECT id FROM t2; -- Right SELECT * FROM t1 WHERE id IN (SELECT id FROM t2); - Check keyword order — Ensure your query follows: SELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY. Nothing out of place between these clauses.
- Remove stray characters — Semicolons inside a PL/SQL block are fine, but not inside a SQL statement. Also watch for apostrophes in string literals that break syntax.
If it still fails
Try this: take the exact query string, paste it into SQL*Plus or SQL Developer as a standalone command (no PL/SQL wrapper). Run it. The error message usually points to a specific line and column. Oracle gives you a line number in the error — count lines from the start of the SQL text. If you're building the query dynamically in code (e.g., concatenating strings in Java or Python), print the final SQL string to a log file. The problem is almost always a syntax error in that string.
Also check for invisible characters — copy-pasting from Word or a PDF can introduce non-ASCII quotes or dashes that look normal but aren't. Retype the suspect parts.
One more thing: if you're using Oracle Database 18c or earlier, the error can appear when you use FETCH FIRST or OFFSET ... ROWS incorrectly — those features were added in 12.1, but the syntax changed across versions. Check your Oracle version with SELECT * FROM v$version;
In short: ORA-00933 is your parser saying "I don't understand this part." The fix is almost always a typo in JOIN syntax, a stray comma, or a missing parenthesis. Once you know what to look for, you'll fix it in under a minute.
Was this solution helpful?