Oracle SQL
Generate Oracle Database 19c-compatible SQL. Prefer metadata-provided object and column names, and apply the following rules to every generated statement.
Namespaces and identifiers
- Treat the service name or PDB as a connection target, not an SQL namespace.
- Qualify objects as
"SCHEMA"."TABLE". Do not generate catalog or database prefixes. - Oracle folds unquoted identifiers to uppercase. Use uppercase double-quoted identifiers for schemas, tables, and columns, especially for reserved words or special characters.
- Use
ASfor column aliases when useful, but never putASbefore a table or subquery alias. - Do not use backticks or square brackets for identifiers.
Queries
- Use
FETCH FIRST n ROWS ONLYinstead ofLIMIT. - For pagination, use
OFFSET n ROWS FETCH NEXT m ROWS ONLYwith a deterministicORDER BY. - Use
FROM DUALwhen selecting expressions without a table, for exampleSELECT 1 FROM DUAL. - Use literals such as
DATE '2026-01-02'andTIMESTAMP '2026-01-02 03:04:05'where appropriate. - Remember that Oracle treats an empty string as
NULL; do not rely on distinguishing the two.
Types and DDL
- Prefer Oracle types such as
VARCHAR2(n),NUMBER(p,s),DATE,TIMESTAMP,CLOB, andBLOB. - Oracle 19c has no SQL
BOOLEANcolumn type orTRUE/FALSESQL literals. Store booleans asNUMBER(1)with1and0. - Do not generate
DROP ... IF EXISTS; check metadata first or use an exception-safe PL/SQL block when conditional DDL is required. - Account for Oracle DDL's implicit commits; do not assume DDL can be rolled back with surrounding DML.
Writes
- Use named bind variables such as
:idfor parameterized statements. - Do not generate multi-row
INSERT ... VALUES (...), (...). Use bound batch execution, separate inserts, or OracleINSERT ALL ... SELECT 1 FROM DUAL. - Do not generate PostgreSQL
ON CONFLICTor MySQLON DUPLICATE KEY UPDATE; use OracleMERGEfor upserts.
PL/SQL program units
- Recognize procedures, functions, package specifications and bodies, triggers, and anonymous blocks as PL/SQL units. Procedures, functions, and anonymous blocks have an optional declarative part, a required executable part, and an optional exception-handling part.
- Treat a procedure as a callable unit without a direct return value; use
OUTorIN OUTparameters for outputs. Treat a function as a callable unit with a declaredRETURNtype andRETURNstatements. - Treat a package specification as the public interface and its package body as the implementation plus private declarations. Resolve packaged members as
SCHEMA.PACKAGE.PROCEDUREorSCHEMA.PACKAGE.FUNCTION. - Recognize overloaded subprograms by their parameter signatures instead of assuming that a name identifies only one procedure or function.
- Treat
BEGIN ... END;andDECLARE ... BEGIN ... END;as complete anonymous blocks. Keep their internal semicolons intact instead of splitting them into ordinary SQL statements. - Omit the trailing
/when sending PL/SQL through a driver;/is a SQL*Plus-style client command that submits the preceding block.
PL/SQL parameters and results
- Interpret parameter modes as
INfor input,OUTfor output, andIN OUTfor a value passed in and returned with possible changes. Recognize omitted modes asIN. - Recognize default parameter values and positional, named (
formal => actual), and mixed invocation notation when resolving arguments. - Recognize
%TYPEand%ROWTYPEdeclarations as types anchored to database columns, rows, variables, or cursors rather than standalone type names. - Recognize explicit cursors, cursor
FORloops, andSYS_REFCURSOR. A REF CURSOR is a handle to a result set that a procedure can expose through anOUTorIN OUTparameter, or that a function can return directly; it is not a direct procedure return value. - Distinguish SQL types from PL/SQL-only types: Oracle 19c table columns cannot use
BOOLEAN, while PL/SQL variables and parameters can. - Treat
DBMS_OUTPUT.PUT_LINEas diagnostic output that clients must explicitly enable and fetch, not as a return value or query result.
PL/SQL control flow and effects
- Interpret
IF,CASE, basic and cursorLOOPforms, local subprograms, and nested blocks as procedural control flow around embedded SQL. - Treat
SELECT ... INTOas a single-row assignment that can raiseNO_DATA_FOUNDorTOO_MANY_ROWS; distinguish it from a query result returned to the caller. - Interpret
EXCEPTIONhandlers according to their control flow.WHEN OTHERSsuppresses the original failure unless it executesRAISEor raises another exception. - Treat
OPEN ref_cursor FOR dynamic_string USING ...as a dynamic query with input binds supplied byUSING; its rows are consumed later withFETCH. Distinguish it from a staticOPEN ref_cursor FOR SELECT .... - Treat
EXECUTE IMMEDIATEseparately:USINGsupplies input binds,INTOreceives single-row query outputs, andRETURNING INTOreceives DML outputs where applicable. - Assume a stored subprogram shares the caller's transaction unless it issues
COMMITorROLLBACKor declaresPRAGMA AUTONOMOUS_TRANSACTION. Do not infer that an unhandled exception automatically rolls back prior work; the caller or host controls the transaction outcome. - Recognize
AUTHID DEFINERas definer-rights execution andAUTHID CURRENT_USERas invoker-rights execution. Account for calls to other routines and triggers when reasoning about reads, writes, privileges, and side effects.
Avoid common dialect leaks
Before returning SQL, reject or rewrite LIMIT, table aliases written with AS, SQL booleans, multi-row VALUES, DROP ... IF EXISTS, PostgreSQL/MySQL upsert syntax, and three- or four-part object names.