Oracle Changesets & Native Command Execution
A practical reference for running Oracle schema and PL/SQL changes using native SQL*Plus/SQLcl execution in Harness Database DevOps. Includes changesets, configuration, supported commands, and a full
A practical reference for running Oracle schema and PL/SQL changes using native SQL*Plus/SQLcl execution in Harness Database DevOps. Includes changesets, configuration, supported commands, and a full changelog example.
This guide covers the Oracle Native Executor: how to opt in per changeset, which settings you can configure, and what is and is not supported. Go to Build a Changelog File for general changelog authoring guidance, and go to Get started with changelogs to review a full changelog example.
What is native execution for Oracle?
Oracle schema changes often depend on tooling and behavior that only SQL*Plus/SQLcl provide, not plain JDBC. Migration scripts already written for Oracle commonly rely on:
PL/SQL blocks, packages, and triggers
SETandSPOOLcommands@script includes
Beyond syntax, these scripts often also encode years of DBA-specific automation and deployment conventions built around a SQLPlus/SQLcl environment. The Oracle Native Executor runs these scripts through an actual SQLPlus/SQLcl process instead of JDBC. Key characteristics:
No JDBC abstraction layer for native changesets.
SQL*Plus/SQLcl-aware execution model.
Compatible with PL/SQL, packages, triggers, SET/SPOOL, and @ includes, subject to the injected preamble below.
SQLcl is bundled in the Oracle image, so there is no extra setup for the common case.
How do I run existing SQL*Plus scripts in a pipeline?
Native execution is opt-in per changeset, not a pipeline-wide setting. Harness Database DevOps supports multiple ways to mark a changeset for native execution; all integrate seamlessly into the standard pipeline execution flow, approvals, and governance model.
In this approach, you add runWith: sqlplus as a key on the changeset in a YAML changelog. This method is well-suited for:
Changelogs already authored in Liquibase YAML
Teams that prefer YAML's compact, nested syntax over XML
How it works:
You add
runWith: sqlplusas a key on the changeset.The referenced SQL file is executed against the target Oracle instance through SQL*Plus/SQLcl, not JDBC.
Only this changeset is affected. Everything else in the changelog keeps running over JDBC.
This syntax is a common fit for PL/SQL packages, triggers, and other scripts that depend on SQL*Plus/SQLcl behavior, for example, referencing an oracle/create_order_package.sql file the same way.
In this approach, the changeset and its runWith flag are declared as comment headers directly inside a .sql file. This method is well-suited for:
Teams that already maintain changelogs as plain SQL files
Migrations with several related PL/SQL changesets in one file
How it works:
You add
runWith:sqlplusto the changeset's comment header.Liquibase parses the file's comment headers to identify changeset boundaries.
At runtime, each
runWith:sqlplusblock is handed to SQL*Plus/SQLcl for execution.
This pattern keeps large, multi-statement PL/SQL scripts in a single reviewable file.
In this approach, you add runWith="sqlplus" directly to the <changeSet> tag. This method is well-suited for:
Changelogs already authored in Liquibase XML
How it works:
You add
runWith="sqlplus"as an attribute on the changeset.SQL*Plus/SQLcl executes the referenced SQL file against your target Oracle instance, not JDBC.
Only this changeset is affected — everything else in the changelog keeps running over JDBC.
This approach keeps existing DBA-authored .sql files untouched.

Supported commands and caveats
The Oracle Native Executor works alongside standard Liquibase commands and database change management. It does not replace them.
Configuration
Set executor options in the pipeline step's globalSettings (or settings: for DB Command/Liquibase Command). Setting names use kebab-case; there are no Harness-proprietary names.
Settings reference
All settings are optional.
Setting
Default
Description
sqlplus-path
/opt/oracle/sqlcl/bin/sql (bundled)
Path to the SQL*Plus/SQLcl executable.
sqlplus-sqlerror
WHENEVER SQLERROR EXIT FAILURE
Behavior on statement error.
sqlplus-timeout
1800
Max seconds the process may run before timing out.
sqlplus-args
—
Extra raw arguments passed to SQL*Plus/SQLcl.
sqlplus-username / sqlplus-password
Falls back to the DB instance JDBC connector credentials
Override login when you need different auth than the DB instance JDBC connector (for example, sys as sysdba).
sqlplus-create-spool
true
Auto-create a spool (output log) file.
sqlplus-keep-temp
false
Keep the generated temp script file after execution.
sqlplus-keep-temp-path
System temp
Where to keep the temp file, if kept.
sqlplus-keep-temp-name
Auto-generated
Name of the kept temp file.
sqlplus-keep-temp-overwrite
true
Whether a re-run overwrites the same temp file name.
Complete example changelog
A full example demonstrating table creation, a stored procedure, procedure invocation, and a query, all run natively.
Best practices and usage notes
Transactions: Native changesets cannot be wrapped in a Liquibase-managed transaction. Always set
runInTransaction="false"and handle commit/rollback logic inside the script itself.Previews are not dry runs: Do not rely on
updateSql/rollbackSqlto validate native changesets before applying them. The output is the raw script, not a simulation of what SQL*Plus will do.Elevated credentials: Only set
sqlplus-username/sqlplus-passwordwhen you need different auth than the DB instance JDBC connector (for example,sys as sysdba). Otherwise, leave credentials on the DB instance so access stays centrally managed.Debugging with temp files: Turn on
sqlplus-keep-temp(and optionally setsqlplus-keep-temp-path/-name) when you need to inspect exactly what was sent to SQL*Plus, then turn it back off for normal runs.Mixed changelogs: It is expected, and often the point, to have a changelog with some changesets on
runWith="sqlplus"and others on plain JDBC. Only tag what genuinely needs native behavior.
Choose the right approach
The choice between the YAML changeset, the XML changeset, and the SQL formatted changelog depends on your team's workflow and how your existing scripts are already organized. YAML is the most common choice for both customers and internal teams.
Use Case
Recommended Approach
Changelog already authored in Liquibase YAML
YAML changeset with runWith: sqlplus
Changelog already authored in Liquibase XML
XML changeset with runWith="sqlplus"
Existing DBA-authored .sql scripts
SQL formatted changelog with runWith:sqlplus
Multiple related PL/SQL changesets in one file
SQL formatted changelog
Referencing a single external script
YAML or XML changeset with sqlFile
Conclusion
Native execution does not mean giving up the database change management capabilities you are already using. Native changesets stay part of the same Liquibase changelog, are tracked the same way, and support the same core commands (update, rollback, rollbackCount, status, history, tag), with runInTransaction="false" required and preview commands treated as informational only.
As a result, Oracle migrations follow the same governed Database DevOps lifecycle as other database workloads in Harness Database DevOps, letting teams bring proven SQL*Plus/SQLcl scripts into automated pipelines without rewriting them for JDBC.
Next steps
Go to Build a Changelog File to structure a changelog mixing JDBC and native Oracle changesets.
Go to Get started with changelogs to review a full end-to-end changelog example.
Go to Automatic and custom rollbacks to configure rollback strategies for your Oracle changesets.
Last updated
Was this helpful?