SQLcl, Oracle's command-line tool for the database, has an APEX command that exports applications without opening App Builder. One command writes an application to a single SQL file, or splits it into one file per page and shared component, which suits Git much better. The same files are installed in another workspace with the APEX_APPLICATION_INSTALL package, under a new application ID if needed. This guide runs the whole round trip: list, export, split, commit to Git, review a change, and import into a second workspace.
What You Need
- SQLcl, which needs Java. The examples use SQLcl 26.3 with Java 21, against Oracle APEX 26.1.
- A source workspace, here DEVOPS_DEV, with its schema DEVOPS_DEV and application 500, Order Tracker: a small app with a report and a form on an ORDERS table.
- A target workspace, here DEVOPS_PROD, with its schema DEVOPS_PROD.
Start SQLcl and connect as the schema that owns the application, for example with sql devops_dev@localhost:1521/freepdb1. The examples run in an empty directory, where SQLcl writes the export files.
List the Applications
Example:
apex list
Output:
WORKSPACE_ID WORKSPACE APPLICATION_ID APPLICATION_NAME BUILD_STATUS LAST_UPDATED_ON LAST_UPDATED_BY 17966849567032340 DEVOPS_DEV 500 Order Tracker Run and Develop 06-10-26 DEVOPS_DEV
Export an Application to One File
Example:
apex export -applicationid 500
Output:
Exporting Workspace DEVOPS_DEV - application 500:Order Tracker File f500.sql created
f500.sql holds the complete application. It is the same kind of file App Builder exports, and it installs the same way.
Split the Export for Git
A single file of thousands of lines is hard to review. With -split, each page and component gets a file of its own:
Example:
apex export -applicationid 500 -split -exporiginalids -skipexportdate -overwrite-files
Output:
Exporting Workspace DEVOPS_DEV - application 500:Order Tracker File f500/install.sql created
- -split writes the f500 directory, with install.sql calling every other file in order.
- -exporiginalids writes the component IDs as they are in the workspace, instead of computing them for the export.
- -skipexportdate leaves the date line out of the files.
- -overwrite-files replaces existing files. Without it, a second export into the same directory does not overwrite: SQLcl writes new files such as page_00002_1.sql next to the old ones.
The directory looks like this:
Example:
ls f500 ls f500/application ls f500/application/pages find f500 -type f | wc -l
Output:
application
install.sql
create_application.sql
delete_application.sql
deployment
end_environment.sql
pages
plugin_settings.sql
set_environment.sql
shared_components
user_interfaces
page_00000.sql
page_00001.sql
page_00002.sql
page_00003.sql
page_00004.sql
page_00005.sql
page_09999.sql
page_groups.sql
45Every page has its own file, and the 45 files together make up the application.
Export a Readable Version
The SQL files are made for installing, not for reading. The APEXLANG export type writes the application as readable text, one .apx file per page and per group of shared components, which makes code reviews easier:
Example:
apex export -applicationid 500 -exptype APEXLANG -dir readable -overwrite-files
Output:
Exporting Workspace DEVOPS_DEV - application 500:Order Tracker File readable/order-tracker/application.apx created
Example:
find readable -name "*.apx" | sort
Output:
readable/order-tracker/application.apx readable/order-tracker/page-groups.apx readable/order-tracker/pages/p00000-global-page.apx readable/order-tracker/pages/p00001-home.apx readable/order-tracker/pages/p00002-orders.apx readable/order-tracker/pages/p00003-order.apx readable/order-tracker/pages/p00004-order-list.apx readable/order-tracker/pages/p00005-order-details.apx readable/order-tracker/pages/p09999-login.apx readable/order-tracker/shared-components/authentications.apx readable/order-tracker/shared-components/authorizations.apx readable/order-tracker/shared-components/breadcrumbs.apx readable/order-tracker/shared-components/build-options.apx readable/order-tracker/shared-components/component-settings.apx readable/order-tracker/shared-components/lists.apx readable/order-tracker/shared-components/lovs.apx readable/order-tracker/shared-components/static-files.apx readable/order-tracker/shared-components/themes/universal-theme/theme.apx
-exptype accepts several types at once, for example APPLICATION_SOURCE,APEXLANG for the installable files and the readable ones together.
Commit the Export to Git
Example:
git init -q git add f500 git commit -q -m "Order Tracker, release 1.0" git log --oneline
Output:
d858d2e Order Tracker, release 1.0
See an Application Change in Git
Here the change is a new version number, set with APEX_APPLICATION_ADMIN, followed by the same split export:
Example:
-- a change in the app: a new version number
begin
apex_util.set_workspace('DEVOPS_DEV');
apex_application_admin.set_application_version(p_application_id => 500, p_version => 'Release 1.1');
commit;
end;
/
apex export -applicationid 500 -split -exporiginalids -skipexportdate -overwrite-filesOutput:
PL/SQL procedure successfully completed. Exporting Workspace DEVOPS_DEV - application 500:Order Tracker File f500/install.sql created
Example:
git status --short git diff -U0 | grep '^[-+][^-+]'
Output:
M f500/application/create_application.sql ?? f500.sql ?? readable/ -,p_flow_version=>'Release 1.0' +,p_flow_version=>'Release 1.1' -,p_version_scn=>'18822141' +,p_version_scn=>'18822354'
- Of the 45 files, only create_application.sql changed: the version, and p_version_scn, which records the database change number of the last change.
- f500.sql and the readable directory were not committed in this example, so Git lists them as untracked.
Import into Another Workspace with a New Application ID
The export contains the application, not its tables. Create the objects it uses in the target schema first, connected as DEVOPS_PROD:
Example:
-- the app's table in the target schema
create table if not exists orders (
order_id number generated by default as identity primary key,
customer_name varchar2(100) not null,
delivery_method varchar2(10) default 'DELIVERY' not null
constraint orders_method_ck check (delivery_method in ('PICKUP', 'DELIVERY')),
delivery_address varchar2(200),
notes varchar2(400));Output:
Table ORDERS created.
Then set the install options and run install.sql of the split export:
Example:
begin
apex_application_install.set_workspace('DEVOPS_PROD');
apex_application_install.set_application_id(600);
apex_application_install.generate_offset;
apex_application_install.set_schema('DEVOPS_PROD');
apex_application_install.set_application_alias('ORDER-TRACKER-PROD');
end;
/
@f500/install.sql
select application_id, application_name, alias, owner, version
from apex_applications where workspace = 'DEVOPS_PROD';Output:
PL/SQL procedure successfully completed.
--install
--application/set_environment
--application/delete_application
--application/create_application
--application/plugin_settings
--application/shared_components/navigation/lists/navigation_bar
--application/shared_components/navigation/lists/navigation_menu
--application/shared_components/navigation/lists/page_navigation
--application/shared_components/navigation/listentry
--application/shared_components/files/icons_app_icon_144_rounded_png
--application/shared_components/files/icons_app_icon_192_png
--application/shared_components/files/icons_app_icon_256_rounded_png
--application/shared_components/files/icons_app_icon_32_png
--application/shared_components/files/icons_app_icon_512_png
--application/shared_components/security/authorizations/administration_rights
--application/shared_components/navigation/navigation_bar
--application/shared_components/logic/application_settings
--application/shared_components/navigation/tabs/standard
--application/shared_components/navigation/tabs/parent
--application/shared_components/user_interface/lovs/boolean
--application/pages/page_groups
--application/shared_components/navigation/breadcrumbs/breadcrumb
--application/shared_components/navigation/breadcrumbentry
--application/shared_components/user_interface/themes
--application/shared_components/user_interface/theme_style
--application/shared_components/user_interface/theme_files
--application/shared_components/user_interface/template_opt_groups
--application/shared_components/user_interface/template_options
--application/shared_components/globalization/language
--application/shared_components/logic/build_options
--application/shared_components/globalization/messages
--application/shared_components/globalization/dyntranslations
--application/shared_components/security/authentications/oracle_apex_accounts
--application/user_interfaces/combined_files
--application/pages/page_00000
--application/pages/page_00001
--application/pages/page_00002
--application/pages/page_00003
--application/pages/page_00004
--application/pages/page_00005
--application/pages/page_09999
--application/deployment/definition
--application/deployment/checks
--application/deployment/buildoptions
--application/end_environment
...done
APPLICATION_ID APPLICATION_NAME ALIAS OWNER VERSION
_________________ ___________________ _____________________ ______________ ______________
600 Order Tracker ORDER-TRACKER-PROD DEVOPS_PROD Release 1.1
1 row selected.- set_workspace names the target workspace.
- set_application_id installs the application as 600, because ID 500 is already used in this APEX instance. generate_offset shifts the internal component IDs so they do not clash with those of application 500.
- set_schema makes DEVOPS_PROD the parsing schema, and set_application_alias gives the copy its own URL alias.
- Running the same block and script again later replaces application 600 with the newer version.
Things to Know
- The single-file export installs the same way: run the same block, then @f500.sql.
- Run the import as the target workspace's schema, or as a user with the APEX_ADMINISTRATOR_ROLE role, as the header of every export file says.
- Commit the export after each change, so Git shows who changed which page and when.
- For applications that change together with tables and code, SQLcl Projects packages both into one release.
Related Guides
- How to Export and Install APEX Applications Using APEX_EXPORT and APEX_APPLICATION_INSTALL
- Oracle APEX Debugging, Source Control, and Going to Production
Conclusion
SQLcl's apex export writes an application to one file or, with -split, to one file per component, ready for Git. Add -overwrite-files when exporting again into the same directory, review changes with git diff, and install the export in another workspace with APEX_APPLICATION_INSTALL, under a new application ID and schema when needed.
