Skip to content
Oracle Database

Oracle Error ORA-00933

SQL command not properly ended

Applies to: Oracle Database 19c, 21c, 23ai and 26ai (wording differs: see below)
Last technically reviewed 24 October 2026 on Oracle Database Error Messages reference (26ai, 21c and 19c); not run locally
The full message
ORA-00933: unexpected keyword at or near LIMIT
Other forms of this message
Oracle Database 19c and 21c
ORA-00933: SQL command not properly ended
SQL*Plus and SQLcl mark where the statement went wrong
ORDER BY order_date DESC LIMIT 10
                         *
ERROR at line 3:
ORA-00933: SQL command not properly ended
Error code
ORA-00933
Product
Oracle Database
Versions
Oracle Database 19c, 21c, 23ai and 26ai (wording differs: see below)
Last reviewed
24 October 2026

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';
What to look for

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-only

Oracle 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 data

UPDATE 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-only

Oracle'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 configuration

Oracle'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;
Expected result (documented format, not run)
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;
Expected result (documented format, not run)
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

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.

Still stuck on an Oracle error?

Browse the full Oracle error library, or get hands-on help from an experienced SQL professional.