Oracle APEX applications move between workspaces and instances as export files: from development to test to production, or into version control. The packages in this guide do from PL/SQL what App Builder's export and import pages and the SQLcl apex export and apex import commands do, so you can use them in deployment scripts, CI pipelines, and backups.
APEX_EXPORT writes applications and workspaces as files, APEX_APPLICATION_INSTALL installs them with a new ID, alias, schema, and other settings, and APEX_APP_OBJECT_DEPENDENCY finds the database objects an application depends on. Each is shown with a tested example and its real output from Oracle APEX 26.1.
Quick Reference
| Task | Subprogram |
|---|---|
| Export an application | APEX_EXPORT.GET_APPLICATION |
| Pack or unpack export files as a ZIP file | APEX_EXPORT.ZIP, UNZIP |
| Export a workspace, its files, or feedback | GET_WORKSPACE, GET_WORKSPACE_FILES, GET_FEEDBACK |
| Read an export file's details before installing | APEX_APPLICATION_INSTALL.GET_INFO |
| Install with a new ID, alias, schema, or name | SET_APPLICATION_ID, GENERATE_OFFSET, SET_SCHEMA, SET_APPLICATION_ALIAS, INSTALL |
| Delete an application | REMOVE_APPLICATION |
| Find the database objects an application uses | APEX_APP_OBJECT_DEPENDENCY.SCAN |
| Load packaged data, refresh subscriptions, generate apps | APEX_DATA_INSTALL, APEX_SHARED_COMPONENT, APEX_GENDEV |
How to Run These Examples
The examples ran in Oracle APEX 26.1 in a workspace named APEXBOOK, whose schema ORBIT holds the Orbit Outfitters sample tables from the orb_tables repository on GitHub. They export a test application with ID 200, called API Lab. Unlike most APEX APIs, these examples need no APEX session: they run in a plain database session after setting the workspace with apex_util.set_workspace. Replace the workspace, schema, and application ID with your own. The output under each example is exactly what the database printed.
Exporting: APEX_EXPORT
GET_APPLICATION
GET_APPLICATION exports an application and returns the files as apex_t_export_files, a list of apex_t_export_file objects, each with a name and contents (a CLOB). p_type chooses the format:
- apex_export.c_type_sql, the default: an installable SQL script.
- c_type_apexlang and c_type_readable_yaml: the readable APEXlang files, which are the same in 26.1.
- c_type_embedded_code: the SQL, PL/SQL, and JavaScript in the application, for code reviews and scanners.
- c_type_checksum_sh1 or c_type_checksum_sh256: a checksum, to detect changes.
p_split => true writes one file per component. APEXlang exports include binary static files, whose content is in contents_blob instead of contents. p_components exports only some components, such as PAGE:8 or LOV:%.
The other parameters decide what goes into the file: p_with_date, p_with_ir_public_reports, p_with_ir_private_reports, p_with_ir_notifications, p_with_translations, p_with_original_ids, p_with_no_subscriptions, p_with_comments, p_with_supporting_objects (Y, N, or I to install them automatically), p_with_acl_assignments, p_with_audit_info (apex_export.c_audit_names_dates or c_audit_dates_only), and p_with_runtime_instances, which lists the background executions, tasks, and workflows to keep.
Syntax:
apex_export.get_application(p_application_id in number, p_type in t_export_type default c_type_sql,
p_split in boolean default false, p_with_date in boolean default false, ...,
p_components in apex_t_varchar2 default null, p_with_audit_info in t_audit_type default null,
p_with_runtime_instances in apex_t_varchar2 default null) return apex_t_export_filesZIP and UNZIP
ZIP packs export files into a ZIP file, the format App Builder downloads and imports, and p_extra_files adds files such as a README. UNZIP unpacks one.
This example needs no APEX session. It exports application 200 in each format, prints the number of files and characters, and then zips and unzips the split export.
Example:
declare
l_files apex_t_export_files;
l_zip blob;
procedure show(p_label varchar2) is
l_chars number := 0;
begin
for i in 1 .. l_files.count loop
l_chars := l_chars + nvl(dbms_lob.getlength(l_files(i).contents), 0);
end loop;
dbms_output.put_line(rpad(p_label, 16) || lpad(l_files.count, 4) || ' file(s), ' || lpad(l_chars, 8)
|| ' chars, first: ' || l_files(1).name);
end;
begin
apex_util.set_workspace('APEXBOOK'); -- outside APEX: the workspace of the application
l_files := apex_export.get_application(p_application_id => 200);
show('SQL');
l_files := apex_export.get_application(p_application_id => 200, p_split => true);
show('SQL, split');
l_files := apex_export.get_application(p_application_id => 200, p_type => apex_export.c_type_readable_yaml);
show('readable YAML');
l_files := apex_export.get_application(p_application_id => 200, p_type => apex_export.c_type_apexlang);
show('APEXlang');
l_files := apex_export.get_application(p_application_id => 200, p_split => true,
p_components => apex_t_varchar2('PAGE:8', 'LOV:%'));
show('page 8 and LOVs');
l_files := apex_export.get_application(p_application_id => 200, p_type => apex_export.c_type_checksum_sh256);
dbms_output.put_line('checksum: ' || substr(l_files(1).contents, 1, 20) || '...');
-- all files in one ZIP, and back
l_files := apex_export.get_application(p_application_id => 200, p_split => true);
l_zip := apex_export.zip(p_source_files => l_files);
dbms_output.put_line('ZIP: ' || round(dbms_lob.getlength(l_zip) / 1024) || ' KB, unzipped: '
|| apex_export.unzip(p_source_zip => l_zip).count || ' files');
end;
/Output:
SQL 1 file(s), 1421315 chars, first: f200.sql SQL, split 143 file(s), 1472400 chars, first: f200/application/set_environment.sql readable YAML 92 file(s), 932364 chars, first: shared-components/themes/universal-theme/static-files.apx APEXlang 92 file(s), 932364 chars, first: shared-components/themes/universal-theme/static-files.apx page 8 and LOVs 27 file(s), 48146 chars, first: f200/application/set_environment.sql checksum: SH256:4Vb5o00UHbdPR4... ZIP: 346 KB, unzipped: 143 files
The ZIP file unpacked to the same 143 files as the split export, and the readable YAML and APEXlang exports were identical, as expected in 26.1. Exporting only page 8 and the LOVs produced a small set of files, which is useful for reviewing one change. Comparing SH256 checksums between runs is a cheap way to tell whether anything changed at all.
Outside APEX, set the workspace first with apex_util.set_workspace. The schema you connect as must be one of the workspace's schemas.
GET_WORKSPACE, GET_WORKSPACE_FILES, and GET_FEEDBACK
GET_WORKSPACE exports a workspace's definition: users, groups, remote servers, and credentials without their secrets, and optionally Team Development (p_with_team_development) and SQL Workshop scripts (p_with_misc). GET_WORKSPACE_FILES exports the static workspace files, and GET_FEEDBACK exports the feedback users entered since a date (p_since), for example to move it from production back to development.
This example needs no APEX session.
Example:
declare
l_ws number;
l_files apex_t_export_files;
begin
apex_util.set_workspace('APEXBOOK');
l_ws := apex_util.find_security_group_id('APEXBOOK');
l_files := apex_export.get_workspace(p_workspace_id => l_ws); -- users, groups, remote servers, ...
dbms_output.put_line('workspace: ' || l_files(1).name || ', ' || dbms_lob.getlength(l_files(1).contents) || ' chars');
l_files := apex_export.get_workspace_files(p_workspace_id => l_ws); -- the static workspace files
dbms_output.put_line('files: ' || l_files(1).name);
l_files := apex_export.get_feedback(p_workspace_id => l_ws); -- the feedback users left
dbms_output.put_line('feedback: ' || l_files(1).name);
end;
/Output:
workspace: w36520348764463069.sql, 4760 chars files: files_36520348764463069.sql feedback: fb36520348764463069.sql
Each file name includes the workspace ID, with a w, files_, or fb prefix for the kind of export.
Installing: APEX_APPLICATION_INSTALL
An application export is a SQL script that installs the application with the ID, workspace, schema, and settings it was exported with. APEX_APPLICATION_INSTALL changes these for the next installation: set the values, then run the script, or call INSTALL with the files. CLEAR_ALL resets all values.
INSTALL, GET_INFO, and REMOVE_APPLICATION
INSTALL installs export files in any format APEX_EXPORT writes, split or not, using the values set before. p_overwrite_existing => true replaces an application with the same ID. GET_INFO reads the files without installing them and returns a t_file_info record: the file type, workspace, APEX version, application ID, name, alias, and owner, the build status, and whether the ID and alias are free in this instance (app_id_usage and app_alias_usage). REMOVE_APPLICATION deletes an application.
Syntax:
apex_application_install.install(p_source in apex_t_export_files default null, p_overwrite_existing in boolean default false) apex_application_install.get_info(p_source in apex_t_export_files) return t_file_info apex_application_install.remove_application(p_application_id in number)
Before it runs, the example removes any application 9200 left over from an earlier run. It then installs a copy of application 200 as 9200 with its own alias and name, checks it, and removes it again. It needs no APEX session.
Example:
declare
l_files apex_t_export_files;
l_info apex_application_install.t_file_info;
begin
apex_util.set_workspace('APEXBOOK');
l_files := apex_export.get_application(p_application_id => 200);
-- what the file contains
l_info := apex_application_install.get_info(p_source => l_files);
dbms_output.put_line('file: application ' || l_info.app_id || ' "' || l_info.app_name || '", alias ' || l_info.app_alias
|| ', workspace ' || l_info.workspace_name || ', APEX ' || l_info.version);
-- install a copy with its own ID, alias, and name
apex_application_install.clear_all;
apex_application_install.set_workspace('APEXBOOK');
apex_application_install.set_application_id(9200);
apex_application_install.generate_offset; -- new internal IDs for the copy
apex_application_install.set_schema('ORBIT');
apex_application_install.set_application_alias('API-LAB-COPY');
apex_application_install.set_application_name('API Lab (copy)');
apex_application_install.set_build_status('RUN_ONLY');
apex_application_install.set_auto_install_sup_obj(p_auto_install_sup_obj => false);
dbms_output.put_line('install as: ' || apex_application_install.get_application_id || ', '
|| apex_application_install.get_application_alias || ', '
|| apex_application_install.get_application_name || ', schema '
|| apex_application_install.get_schema || ', ' || apex_application_install.get_build_status);
apex_application_install.install(p_source => l_files);
for a in (select application_id, application_name, alias, build_status, pages
from apex_applications where application_id = 9200) loop
dbms_output.put_line('installed: ' || a.application_id || ' "' || a.application_name || '", '
|| a.alias || ', ' || a.build_status || ', ' || a.pages || ' pages');
end loop;
apex_application_install.remove_application(p_application_id => 9200);
dbms_output.put_line('removed');
end;
/Output:
file: application 200 "API Lab", alias API-LAB, workspace , APEX 2026.03.30 install as: 9200, API-LAB-COPY, API Lab (copy), schema ORBIT, RUN_ONLY API Last Extended:20260330 Your Current Version:20260330 This import is compatible with version: 20260330 COMPATIBLE (You should be able to run this import without issues.) ID offset during import: 43018123787394834 New ID offset for application: 0 ------------------------------------------------------------------ WARNING for credential "credentials-for-local-ollama" (Static ID): - Oracle APEX export files do not contain credential information. - Use the APEX_CREDENTIAL.SET_PERSISTENT_CREDENTIAL procedure to set the - credentials after the application has been imported. The credential is being - referenced with its static ID "credentials-for-local-ollama" -------------------------------------------------------------- ... elapsed: 3.02 sec installed: 9200 "API Lab (copy)", API-LAB-COPY, Run Only, 49 pages removed
GET_INFO reported the application's ID, name, alias, and APEX version, but the workspace name came back empty, so do not rely on that field. The installation wrote its log to DBMS_OUTPUT, just as the SQL script would in SQL*Plus, including the compatibility check and a warning that credentials are not exported. Set them again after installing with APEX_CREDENTIAL, as shown in the guide to APEX_WEB_SERVICE and APEX_CREDENTIAL.
GENERATE_OFFSET is what makes a second copy possible in the same instance: every internal component ID of the copy is shifted, so it cannot collide with the original.
The Settings
Each SET_ procedure has a GET_ function that returns the value set, as the example did with GET_APPLICATION_ID and GET_SCHEMA. SET_REMOTE_SERVER has eight: GET_REMOTE_SERVER_BASE_URL, GET_REMOTE_SERVER_HTTPS_HOST, GET_REMOTE_SERVER_DEFAULT_DB, GET_REMOTE_SERVER_SQL_MODE, GET_REMOTE_SERVER_AI_MODEL, GET_REMOTE_SERVER_AI_HEADERS, GET_REMOTE_SERVER_AI_ATTRS, and GET_REMOTE_SERVER_AI_MAXTOKENS, each taking the static ID.
| Procedures | Setting |
|---|---|
| SET_WORKSPACE(p_workspace), SET_WORKSPACE_ID(p_workspace_id) | The workspace to install into. |
| SET_APPLICATION_ID(p_application_id), GENERATE_APPLICATION_ID | The application ID, or a new unused one. |
| SET_OFFSET(p_offset), GENERATE_OFFSET | The offset added to all internal component IDs, needed to install a second copy in the same instance. |
| SET_SCHEMA(p_schema) | The parsing schema. |
| SET_APPLICATION_ALIAS, SET_APPLICATION_NAME | The alias and name. |
| SET_BUILD_STATUS(p_build_status) | RUN_ONLY or RUN_AND_BUILD. |
| SET_IMAGE_PREFIX, SET_PROXY(p_proxy, p_no_proxy_domains) | The static files prefix, and the proxy for web services. GET_PROXY and GET_NO_PROXY_DOMAINS read them. |
| SET_AUTHENTICATION_SCHEME(p_name) | The authentication scheme to make current. |
| SET_AUTO_INSTALL_SUP_OBJ(p_auto_install_sup_obj) | Whether to run the supporting objects' installation scripts. |
| SET_THEME_ID, SET_REST_SOURCE_CATALOG_GROUP | The theme number, and the catalog group of REST sources. |
| SET_REMOTE_SERVER(p_static_id, p_base_url, p_https_host, p_default_database, p_mysql_sql_modes, p_ords_timezone, p_ai_model_name, p_ai_http_headers, p_ai_attributes, p_ai_max_tokens) | A remote server's URL and settings for this instance, such as a production AI or REST endpoint. |
| SET_KEEP_SESSIONS, SET_KEEP_BACKGROUND_EXECS, SUSPEND_BACKGROUND_EXECS, SET_MAX_SCHEDULER_JOBS | Keep users' sessions and background executions when replacing the application, suspend running executions, and limit the jobs of background executions. |
| SET_PASS_ECID | Whether web service calls pass the ECID. |
| SET_SUBSCRIPTION_MODE, SET_SUBSCRIPTION_MAPPING | New in 26.1. How subscribed components are refreshed, and which master applications they map to. |
| SET_DATASET_IMPORT_MODE, CLEAR_DATASET_IMPORT_MODES, ADD_DATA_REPORTER_REMAP, CLEAR_DATA_REPORTER_REMAP, GET_DATA_REPORTER_REMAP | How the application's data sets and data reporter queries are imported. |
SET_REMOTE_SERVER is the one to remember for deployments: it points the installed application at the production endpoint without editing the export file. The declarative deployment steps are covered in the guide to debugging and deploying Oracle APEX applications.
Dependencies: APEX_APP_OBJECT_DEPENDENCY
SCAN and CLEAR_CACHE
SCAN finds the database objects an application, or one page of it, uses: tables, views, columns, packages, and their procedures, in queries, PL/SQL, conditions, and plug-ins. It also finds SQL and PL/SQL that no longer compiles. The results go into the views APEX_USED_DB_OBJECTS, APEX_USED_DB_OBJ_DEPENDENCIES, and APEX_USED_DB_OBJECT_COMP_PROPS, which App Builder's Database Object Dependencies report shows. p_options is c_option_all, c_option_dependencies, c_option_identifiers (PL/Scope identifiers), or c_option_errors. CLEAR_CACHE deletes the results.
Syntax:
apex_app_object_dependency.scan(p_application_id in number, p_page_id in number default null,
p_options in varchar2 default c_option_all)
apex_app_object_dependency.clear_cache(p_application_id in number)This example needs no APEX session. It scans page 8, queries the results, and clears them.
Example:
begin
apex_util.set_workspace('APEXBOOK');
-- which database objects does page 8 (Orders) use?
apex_app_object_dependency.scan(p_application_id => 200, p_page_id => 8,
p_options => apex_app_object_dependency.c_option_dependencies);
end;
/
select referenced_type, referenced_name, usage_count
from apex_used_db_objects
where application_id = 200 and referenced_owner = 'ORBIT'
order by referenced_type, referenced_name;
begin
apex_app_object_dependency.clear_cache(p_application_id => 200);
end;
/Output:
REFERENCED_TYPE REFERENCED_NAME USAGE_COUNT --------------- --------------- ----------- PACKAGE ORB_AUTH 2 PACKAGE ORB_SALES 6 TABLE LAB_CITIES 1 TABLE ORB_CATEGORIES 1 TABLE ORB_CUSTOMERS 13 TABLE ORB_EMPLOYEES 5 TABLE ORB_ORDERS 9 TABLE ORB_ORDER_ITEMS 1 TABLE ORB_PRODUCTS 1 TABLE ORB_SUPPLIERS 1 TABLE ORB_WAREHOUSES 1 VIEW ORB_ORDERS_V 19 VIEW ORB_ORDER_DV 1 VIEW ORB_PRODUCTS_V 6
The query lists each object in the ORBIT schema that the scan found, with how often it is used. A list like this answers the question before any schema change: which parts of the application will this break?
The scan needs the CREATE PROCEDURE privilege in the parsing schema, and it finds calls inside packages only in code compiled with PL/Scope. It does not run Function Body Returning SQL code, so the queries such functions build are not scanned.
The Smaller Lifecycle Packages
| Subprogram | Purpose |
|---|---|
| APEX_DATA_INSTALL.LOAD_SUPPORTING_OBJECT_DATA(p_table_name, p_delete_after_install, p_app_id) | In a supporting objects script, loads the data packaged with the application into a table. |
| APEX_SHARED_COMPONENT.REFRESH(p_component_type, p_component_id) | Refreshes a subscribed component from its master. |
| APEX_SHARED_COMPONENT.PUBLISH(p_component_type, p_component_id) | Publishes a master component to its subscribers. |
| APEX_EXTENSION.ADD_MENU_ENTRY(p_label, p_url, ...), REMOVE_MENU_ENTRY | Add or remove a link in the Extension Menu of an extension workspace. |
| APEX_EXTENSION.SET_WORKSPACE(p_id | p_name), GET_GRANTOR_WORKSPACE, GET_BUILDER_LINK(p_app_id, p_page_id, ...) | In an extension app, work with the metadata of the workspace that granted access, and link into its App Builder. |
| APEX_GENDEV.PROCESS_BLUEPRINT(p_blueprint, p_parsing_log, p_apexlang_zip) | Turns an app blueprint (JSON) into APEXlang files, as the Create App Wizard does. |
The p_component_type of APEX_SHARED_COMPONENT is one of its constants, such as c_authentication, c_lov, c_plugin, c_rest_data_source, c_ai_agent, or c_page (a pattern page). An extension workspace hosts applications that extend App Builder for other workspaces, for example a custom code review tool, and those workspaces subscribe to its menu.
Conclusion
APEX_EXPORT exports applications as SQL, split files, APEXlang, embedded code, or checksums, along with workspaces, static files, and feedback, and ZIP and UNZIP package them. APEX_APPLICATION_INSTALL reads an export's details, then installs it with a new ID, offset, schema, alias, name, build status, remote servers, and more. APEX_APP_OBJECT_DEPENDENCY finds the database objects an application depends on. APEX_DATA_INSTALL, APEX_SHARED_COMPONENT, APEX_EXTENSION, and APEX_GENDEV load packaged data, publish and refresh subscriptions, extend App Builder, and generate applications from blueprints.
