Oracle SQL scripts churned out by large-language-model (LLM) agents can look flawless on paper and still explode in production. In a 2.3 million-line legacy codebase, an AI-driven agent routinely slipped in identifiers that didn’t exist – for example, using POLICY_STATUS instead of the real STATUS_CD column, or referring to a non-existent CUSTOMERS table rather than CUSTOMER.
Running the script to catch the typo isn’t an option for UPDATE or DELETE statements. Executing them on a production-like dataset acquires locks, burns sequence numbers and can trigger cascading side-effects. Developers need a way to validate names and syntax without touching any data. The answer, surprisingly simple, is Oracle’s EXPLAIN PLAN command – repurposed as a linting step.
How EXPLAIN PLAN works as a fast validator
When Oracle receives a statement, it first parses it. Parsing checks that every referenced table, column and privilege exists, then builds an execution plan and writes that plan to a system table. The command never runs the statement: no rows are modified, no triggers fire, no locks are taken. If the parser hits an unknown object, it throws an error in a few milliseconds.
That behavior makes EXPLAIN PLAN a perfect pre-flight check for AI-generated SQL. A missing table or column is reported instantly, letting the generation loop correct the mistake before a human ever sees the script.
The workflow I wired into my CI pipeline
- Split the incoming script into individual statements.
- Run
EXPLAIN PLAN FOR <statement>against a development schema. - Collect any parsing errors Oracle returns.
- Feed the errors back to the LLM for a retry.
In practice, a single retry clears the majority of naming errors. The AI learns the correct schema and adjusts its output automatically. I also lock the agent into read-only mode: it may issue SELECTs and EXPLAIN PLAN calls, but DDL, DML and COMMIT are blocked. That sandbox guarantees the database stays untouched while the AI probes its structure.
Beyond name checks, the generated plan reveals obvious performance red flags. If a statement would trigger a full-table scan on a massive table, the plan shows it before any rows are touched, giving developers a chance to suggest indexes or rewrite the predicate.
Limits of the approach
- Logical correctness isn’t verified. A statement that references the right columns but applies the wrong filter still passes the lint.
- PL/SQL blocks are out of scope. The parser only handles individual SQL statements; procedural code needs a separate validation path.
- Data-level validation is missing. The lint cannot tell you whether a literal value conforms to a column’s domain or whether a foreign-key reference actually exists.
- Dev schema only. Errors that appear only in production – for example, a table that exists in dev but is renamed in prod – remain invisible until later.
These gaps don’t diminish the utility of the method; they simply define its perimeter. For most LLM-generated DML scripts, the most common failure mode is a typo or a wrong object name, and that’s exactly what EXPLAIN PLAN catches.
Portability to other database engines
The same principle applies beyond Oracle. PostgreSQL’s PREPARE statement or EXPLAIN can parse a query without execution. SQL Server offers SET PARSEONLY ON, which forces the engine to validate syntax and object names while skipping actual processing. Any RDBMS that separates parsing from execution can become a lightweight linting gate.
Takeaway
Running EXPLAIN PLAN (or its equivalent) on every AI-generated SQL statement turns a database parser into an inexpensive, zero-risk linting gate. It catches the most frequent naming and syntax errors before any data moves, keeping legacy systems stable while letting developers reap the productivity boost of LLM-assisted coding.
