- Error code
- ORA-00933
- Product
- Oracle Database
- Versions
- Oracle Database 19c, 21c, 23ai and 26ai (wording differs: see below)
- Category
- SQL Syntax & Query Structure
- Last reviewed
- 24 October 2026
On this page
What it means
ORA-00933 means Oracle parsed a complete statement and then found more text it did not expect: a clause Oracle does not support, a clause in the wrong place, or the rest of a string that ended too early. Current releases word it as "unexpected keyword at or near ..."; 19c says "SQL command not properly ended".
The parser reads the statement clause by clause. When it reaches a word that cannot continue the statement at that point, it stops and reports ORA-00933. Current releases name the keyword at or near the problem (shortened if it is long); 19c and 21c only say that the command was not properly ended. Oracle's reference lists the causes: a typo, unsupported syntax for a clause, an unsupported clause, or a string that ended early because of an apostrophe, so that the rest of it is read as keywords.
Most cases come from SQL written for another database. Oracle has no LIMIT clause (use FETCH FIRST n ROWS ONLY or ROWNUM), and UPDATE and DELETE do not take ORDER BY. Oracle's reference adds two less obvious cases for current releases: if the keyword in the message does not appear in your statement and CURSOR_SHARING is set to FORCE, an unexpected bind variable was found; and if a function you call builds and runs its own statement, the problem may be in that generated statement.
Common causes
- A clause from another database, such as LIMIT, or a clause Oracle does not accept in that statement, such as ORDER BY in UPDATE or DELETE.
- A typo or a missing keyword that makes the following words impossible to parse, for example a missing comma or operator.
- An apostrophe inside a string literal ends the string early, so the rest of the text is read as SQL.
- Two statements are sent in one call from application code, or a statement has extra text after its end.
- With CURSOR_SHARING set to FORCE, Oracle's reference says an unexpected bind variable can be found in the statement; the keyword in the message then does not appear in your SQL.
Diagnose it
Read-only These queries only read the data dictionary (USER_, ALL_ and DBA_ views) and dynamic performance views (V$). They do not change data, privileges or settings, so they are safe to run first. DBA_ and V$ views need the matching privileges.
Read the keyword or position Oracle reports
On current releases the message names the keyword at or near the error. On 19c, use the asterisk and line number in SQL*Plus or SQLcl, or the position from your tool. Check that clause against the Oracle syntax for the statement: it is often valid in another database but not in Oracle.
Is CURSOR_SHARING set to FORCE?
Relevant when the keyword in the message is not in your statement at all. V$PARAMETER needs SELECT_CATALOG_ROLE or a grant from the DBA; SQL*Plus users can also run SHOW PARAMETER cursor_sharing.
SELECT name, value, isses_modifiable
FROM v$parameter
WHERE name = 'cursor_sharing'; EXACT is the default. FORCE means literals are replaced by bind variables before parsing, which Oracle names as a possible cause of this error.
Check string literals for apostrophes
Search the statement for values such as O'Brien or it's. In generated SQL, log the final statement text before it is executed: an apostrophe in user input that ends a literal early is both a syntax error and a sign of SQL injection risk.
How to fix it
Each fix is labelled with what it changes. Try read-only checks and the least invasive fix first, and test changes outside production.
Use Oracle's row-limiting clause instead of LIMIT
Read-onlyOracle Database 12c and later support OFFSET ... FETCH FIRST n ROWS ONLY; always give an ORDER BY so the result is deterministic.
SELECT id, customer_id, order_date
FROM shop.orders
ORDER BY order_date DESC
FETCH FIRST 10 ROWS ONLY;
Remove clauses Oracle does not allow in the statement
Changes dataUPDATE and DELETE work on every row that matches the WHERE clause; they take no ORDER BY or LIMIT. Make the WHERE clause select exactly the rows you mean, using a subquery if you need "the first N": sort in an inline view and limit the rows outside it.
UPDATE shop.orders
SET status = 'ARCHIVED'
WHERE id IN (
SELECT id FROM (
SELECT id FROM shop.orders
WHERE status = 'CLOSED'
ORDER BY order_date
)
WHERE ROWNUM <= 100
);
Escape apostrophes, or better, use bind variables
Read-onlyOracle's documented fix is to write two single quotes for an apostrophe inside a string, or use alternative quoting with q'[...]'. In application code, pass values as bind variables so quoting never comes into it.
SELECT id FROM shop.customers WHERE last_name = 'O''Brien';
SELECT id FROM shop.customers WHERE last_name = q'[O'Brien]';
Retry with CURSOR_SHARING = EXACT for the session
Changes configurationOracle's Action text suggests setting CURSOR_SHARING to EXACT and running the statement again when FORCE is in use; this either resolves the error or gives more information. Change it for your session only, as a diagnostic step.
ALTER SESSION SET cursor_sharing = EXACT;
Examples
LIMIT copied from MySQL or PostgreSQL
Not reproduced here: no Oracle Database is installed for this site. The result follows the current message format in Oracle's error reference, with the word at the error filled in; exactly which word Oracle names is illustrative. Oracle Database 19c prints "ORA-00933: SQL command not properly ended".
SELECT id, customer_id, order_date
FROM orders
ORDER BY order_date DESC LIMIT 10;
ORA-00933: unexpected keyword at or near LIMIT
ORDER BY in an UPDATE
Not reproduced here: no Oracle Database is installed for this site. The result is shown in the 19c form from Oracle's error reference; current releases word it as "unexpected keyword at or near" followed by the keyword. Oracle's UPDATE syntax has no ORDER BY clause.
UPDATE orders
SET status = 'ARCHIVED'
WHERE status = 'CLOSED'
ORDER BY order_date;
ORA-00933: SQL command not properly ended
How to prevent it
When porting queries from MySQL, PostgreSQL or SQL Server, check each clause against Oracle's syntax: FETCH FIRST instead of LIMIT or TOP, no ORDER BY in UPDATE or DELETE. Test against the oldest Oracle release you support, because newer releases accept syntax older ones reject.
Always use bind variables for values in application code. That removes apostrophe problems entirely and protects against SQL injection at the same time.
Common questions
How do I fix ORA-00933 SQL command not properly ended?
Look at the clause where Oracle stopped. Replace syntax from other databases (LIMIT becomes FETCH FIRST n ROWS ONLY), remove clauses the statement does not allow (ORDER BY in UPDATE), and double any apostrophe inside a string.
What does "unexpected keyword at or near" mean?
It is the same error in Oracle's current wording. The word after "near" is where the parser stopped, which is usually the clause to fix. Oracle Database 19c reports it as "SQL command not properly ended".
Does Oracle support LIMIT?
No. Use the row-limiting clause, for example ORDER BY order_date DESC FETCH FIRST 10 ROWS ONLY (Oracle Database 12c and later), or ROWNUM on older releases.
Learn more on CodeWithSQL
Official documentation
- ORA-00933 (Oracle Database Error Messages)
- SELECT: row_limiting_clause (Oracle SQL Language Reference 19c)
- UPDATE (Oracle SQL Language Reference 19c)
- Literals (Oracle SQL Language Reference 19c)
Last technically reviewed 24 October 2026; examples and diagnostics run on Oracle Database Error Messages reference (26ai, 21c and 19c); not run locally. Messages and explanations follow Oracle's Database Error Messages reference; no Oracle Database was available, so the examples were not run locally.