ORA-00921: Unexpected End of SQL Command — Causes, Fixes & Prevention
ORA-00921 is a SQL syntax error thrown by Oracle when the parser encounters the end of a SQL statement before it is grammatically complete. In simple terms, Oracle expected more keywords or clauses to follow, but the input ended prematurely. This error is especially common in dynamically generated SQL within application code or when writing queries manually in tools like SQL*Plus or SQL Developer.
Top 3 Causes and Fixes
Cause 1: Missing Required Clause (FROM, VALUES, SET, etc.)
The most frequent trigger for ORA-00921 is omitting a mandatory clause in a DML statement.
-- ❌ Triggers ORA-00921: Missing FROM clause
SELECT employee_id, first_name, last_name;
-- ✅ Fixed: FROM clause added
SELECT employee_id, first_name, last_name
FROM employees;
-- ❌ Triggers ORA-00921: Missing VALUES clause
INSERT INTO departments (department_id, department_name);
-- ✅ Fixed: VALUES clause added
INSERT INTO departments (department_id, department_name)
VALUES (10, 'IT Support');
-- ❌ Triggers ORA-00921: Missing SET clause
UPDATE employees
WHERE employee_id = 100;
-- ✅ Fixed: SET clause added
UPDATE employees
SET salary = salary * 1.1
WHERE employee_id = 100;
Quick Fix: Always verify that every DML statement contains its full set of required clauses before execution.
Cause 2: Unmatched Parentheses or Incomplete Subquery
An unclosed parenthesis in a subquery or IN clause will cause Oracle to keep reading until it finds a closing ) — and if the statement ends first, ORA-00921 is raised.
-- ❌ Triggers ORA-00921: Missing closing parenthesis
SELECT *
FROM employees
WHERE department_id IN (
SELECT department_id
FROM departments
WHERE location_id = 1700
;
-- ✅ Fixed: Closing parenthesis added
SELECT *
FROM employees
WHERE department_id IN (
SELECT department_id
FROM departments
WHERE location_id = 1700
);
Quick Fix: Use an IDE with bracket-matching highlighting (SQL Developer, DBeaver, Toad) to instantly spot unmatched parentheses.
Cause 3: Misplaced Comments or Special Characters Cutting the Statement Short
A block comment /* */ that accidentally wraps a critical keyword, or a semicolon ; placed in the middle of a dynamically built SQL string, can cause Oracle to treat the statement as prematurely terminated.
-- ❌ Triggers ORA-00921: Block comment swallows the FROM clause
SELECT employee_id, first_name /* employee name column
FROM employees */
WHERE department_id = 10;
-- ✅ Fixed: Comment placed correctly
SELECT employee_id, first_name /* employee name column */
FROM employees
WHERE department_id = 10;
For dynamic SQL in PL/SQL, always use bind variables instead of string concatenation to avoid accidental injection of special characters that break SQL structure.
-- ❌ Risky: String concatenation can break SQL structure
-- v_sql := 'SELECT * FROM employees WHERE last_name = ''' || v_input || '''';
-- ✅ Safe: Bind variable approach
DECLARE
v_sql VARCHAR2(500);
v_name VARCHAR2(50) := 'King';
v_count NUMBER;
BEGIN
v_sql := 'SELECT COUNT(*) FROM employees WHERE last_name = :1';
EXECUTE IMMEDIATE v_sql INTO v_count USING v_name;
DBMS_OUTPUT.PUT_LINE('Result: ' || v_count);
END;
/
Prevention Tips
1. Use SQL formatters and linters in your development workflow.
Tools like SQL Developer's built-in formatter, or open-source linters like SQLFluff, can automatically detect incomplete statements, unmatched parentheses, and missing clauses before code reaches production. Integrating these into your CI/CD pipeline adds a safety net against syntax errors at the deployment stage.
2. Log and validate dynamically generated SQL before execution.
Whenever SQL is built dynamically in application code or PL/SQL, log the final SQL string before executing it. During development, print it with DBMS_OUTPUT.PUT_LINE, copy it into SQL Developer, and run it manually to confirm it is syntactically complete. This single habit eliminates the majority of dynamic SQL-related ORA-00921 incidents in production environments.
Related Oracle Errors
| Error Code | Description |
|---|---|
| ORA-00900 | Invalid SQL statement |
| ORA-00907 | Missing right parenthesis |
| ORA-00933 | SQL command not properly ended |
| ORA-00936 | Missing expression |
📖 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)