For the complete documentation index, see llms.txt. This page is also available as Markdown.

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

  • SET and SPOOL commands

  • @ 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.

Harness injects its own preamble around your script: SET DEFINE OFF, SET ECHO ON, SET SQLBLANKLINES ON, plus its own SPOOL/EXIT handling. SET DEFINE OFF means substitution variables (&var) are not processed; they run as literal text, not resolved values. If your script uses @ includes or its own SPOOL commands, review how they interact with this injected preamble before relying on them.

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.

At a high level: a developer or DBA commits a migration → Liquibase tracks the changeset → the Oracle Native Executor runs the selected changesets through SQL*Plus/SQLcl → migration status and history remain part of the Liquibase workflow.

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: sqlplus as 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:sqlplus to the changeset's comment header.

  • Liquibase parses the file's comment headers to identify changeset boundaries.

  • At runtime, each runWith:sqlplus block 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:

Most customers and internal teams use the YAML changeset format instead — see the YAML Changeset tab. Use XML mainly if you are already maintaining an XML-based changelog.

  • 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.

Oracle native executor flow from changeset to SQL*Plus/SQLcl

Supported commands and caveats

The Oracle Native Executor works alongside standard Liquibase commands and database change management. It does not replace them.

Transaction handling

runInTransaction="true" is rejected by Liquibase when combined with runWith="sqlplus". Set runInTransaction="false" on every native changeset, and handle commit/rollback logic inside the script itself.

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

  1. Transactions: Native changesets cannot be wrapped in a Liquibase-managed transaction. Always set runInTransaction="false" and handle commit/rollback logic inside the script itself.

  2. Previews are not dry runs: Do not rely on updateSql/rollbackSql to validate native changesets before applying them. The output is the raw script, not a simulation of what SQL*Plus will do.

  3. Elevated credentials: Only set sqlplus-username/sqlplus-password when 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.

  4. Debugging with temp files: Turn on sqlplus-keep-temp (and optionally set sqlplus-keep-temp-path/-name) when you need to inspect exactly what was sent to SQL*Plus, then turn it back off for normal runs.

  5. 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

Last updated

Was this helpful?