ORA-00933: SQL Command Not Properly Ended — Causes, Fixes & Prevention
ORA-00933 is one of the most common Oracle SQL parsing errors, triggered when a SQL statement contains a clause that is not syntactically valid for that command type. In most cases, it means you've appended a keyword or clause that Oracle simply does not allow in that context. The good news: it's almost always a straightforward fix once you identify the offending clause.
Top 3 Causes
1. Using ORDER BY in DML Statements (INSERT / UPDATE / DELETE)
Oracle does not allow ORDER BY in DML statements. Developers migrating from MySQL or SQL Server often carry this habit over, causing immediate failures.
-- WRONG: ORDER BY in a DELETE statement
DELETE FROM employees
WHERE department_id = 10
ORDER BY hire_date;
-- ORA-00933: SQL command not properly ended
-- CORRECT: Remove ORDER BY from DML
DELETE FROM employees
WHERE department_id = 10;
-- CORRECT: If order matters, use PL/SQL
BEGIN
FOR rec IN (SELECT employee_id FROM employees
WHERE department_id = 10
ORDER BY hire_date) LOOP
DELETE FROM employees WHERE employee_id = rec.employee_id;
END LOOP;
COMMIT;
END;
/
2. Using ORDER BY Inside INSERT ... SELECT
Adding an ORDER BY clause to an INSERT ... SELECT statement will throw ORA-00933. The order of rows inserted into a table is meaningless without an explicit ORDER BY on retrieval, so Oracle rejects it at the DML level.
-- WRONG: ORDER BY inside INSERT...SELECT
INSERT INTO dept_backup (department_id, department_name)
SELECT department_id, department_name
FROM departments
ORDER BY department_id;
-- ORA-00933: SQL command not properly ended
-- CORRECT: Remove ORDER BY
INSERT INTO dept_backup (department_id, department_name)
SELECT department_id, department_name
FROM departments;
3. Using GROUP BY or HAVING in UPDATE / DELETE
Clauses like GROUP BY and HAVING belong exclusively to SELECT statements. Attempting to use them in an UPDATE or DELETE context will immediately trigger ORA-00933.
-- WRONG: GROUP BY inside UPDATE
UPDATE employees
SET salary = salary * 1.1
WHERE department_id = 20
GROUP BY department_id;
-- ORA-00933: SQL command not properly ended
-- CORRECT: Use a subquery instead
UPDATE employees
SET salary = salary * 1.1
WHERE department_id IN (
SELECT department_id
FROM departments
WHERE location_id = 1700
);
Quick Fix Solutions
-
Remove disallowed clauses from DML statements. Oracle's DML only supports
WHEREfor filtering. -
Use subqueries to handle complex filtering logic that would otherwise require
GROUP BYorHAVING. -
Use FETCH FIRST (Oracle 12c+) for row-limiting instead of misplaced
ORDER BYworkarounds:
-- Clean pagination in Oracle 12c+
SELECT employee_id, first_name, salary
FROM employees
ORDER BY salary DESC
FETCH FIRST 10 ROWS ONLY;
-- Oracle 11g and below
SELECT * FROM (
SELECT employee_id, first_name, salary
FROM employees
ORDER BY salary DESC
) WHERE ROWNUM <= 10;
Prevention Tips
Use an IDE with SQL syntax validation — Tools like SQL Developer, Toad, or DBeaver highlight invalid clauses in real time before execution, catching ORA-00933 at the source.
Establish a cross-DBMS migration checklist — When porting queries from MySQL, PostgreSQL, or SQL Server, always review DML-specific syntax rules. Create a team-shared reference document mapping non-Oracle syntax (e.g.,
LIMIT,TOP,DELETE ... ORDER BY) to their Oracle equivalents.
Related Errors
-
ORA-00907 –
missing right parenthesis: Often appears alongside ORA-00933 in subquery issues. -
ORA-00936 –
missing expression: Triggered by incomplete or misplaced expressions in a SQL statement. -
ORA-00904 –
invalid identifier: Can co-occur when fixing ORA-00933 introduces a column reference issue.
📖 Want a more detailed guide?
Check out the full in-depth version (Korean) on oraerror.com — includes detailed analysis, additional SQL examples, and prevention tips.
Top comments (0)