ORA-00911 means the SQL text contains a character that has no meaning at that position in Oracle SQL. It often comes from SQL written for another database or tool: a # comment from MySQL, a ? placeholder from JDBC, or a stray backslash. In Oracle AI Database 26ai the message shows the character and what came before it, which makes the culprit easy to find.
Reproduce the Error
Each statement is run with EXECUTE IMMEDIATE, so Oracle receives the text exactly as written, and the error message is printed:
Example:
-- each statement is sent exactly as written, through dynamic SQL
declare
type t_list is table of varchar2(200);
v_sql t_list := t_list(
'select count(*) from dual # MySQL-style comment',
'select count(*) from dual where dummy = ?', -- JDBC-style placeholder
'select count(*) from dual where 1 = 1 \');
v_n number;
begin
for i in 1 .. v_sql.count loop
begin
execute immediate v_sql(i) into v_n;
exception
when others then dbms_output.put_line(sqlerrm);
end;
end loop;
end;
/Output:
ORA-00911: #: invalid character after DUAL ORA-00911: ?: invalid character after = ORA-00911: \: invalid character after <number> PL/SQL procedure successfully completed.
- # starts a comment in MySQL, but not in Oracle.
- ? is a placeholder in JDBC and ODBC; Oracle SQL text uses named binds such as :d.
- A backslash has no meaning in Oracle SQL outside a string.
Fix: Use Oracle Syntax
Write comments with -- or /* */, and bind values with named placeholders and USING:
Example:
declare
v_n number;
begin
-- an Oracle comment, and a named bind variable with USING
execute immediate 'select count(*) from dual where dummy = :d -- a comment'
into v_n using 'X';
dbms_output.put_line('rows: ' || v_n);
end;
/Output:
rows: 1 PL/SQL procedure successfully completed.
Other Common Causes
- Characters pasted from documents or web pages, such as curly quotes or non-breaking spaces; in the test, curly quotes around a value gave ORA-01756 instead, quoted string not properly terminated.
- Special characters such as $ or # at the start of an unquoted name; they are allowed only after the first character.
- In older releases, a semicolon at the end of a statement passed to EXECUTE IMMEDIATE raised ORA-00911; Oracle AI Database 26ai accepted it in the test.
Things to Know
- Client tools such as SQLcl and SQL*Plus interpret some characters themselves before sending the statement, so test generated SQL the way the application sends it.
- Retype quotes and minus signs in SQL copied from formatted documents.
Related Guides
- How to Fix ORA-00907: Missing Right Parenthesis in Oracle
- How to Prevent SQL Injection with DBMS_ASSERT in PL/SQL
Conclusion
ORA-00911 points to a character Oracle does not accept where it appears, usually syntax from another database or text pasted from a document. Read the character from the message, then use Oracle comments, named binds, and plain quotes.
