Skip to main content

Command Palette

Search for a command to run...

Calling PL/SQL from JavaScript in Oracle APEX with AJAX

Updated
•View as Markdown
Calling PL/SQL from JavaScript in Oracle APEX with AJAX
D
Oracle ACE Pro, founder of Enrol Consulting, and Oracle Database and APEX developer with more than two decades of experience building data-driven business applications. I write about Oracle Database, APEX, cloud and AI-assisted development.

Updated from 2023

This article is an updated English version of a post I originally published in Hungarian in 2023. Read the original Hungarian version →

Oracle APEX does an excellent job of supporting declarative application development.

In Page Designer, we can build a page using components, configure their properties, add a few processes or validations, and very quickly have a working business application.

But sometimes we want to execute server-side logic without submitting and rebuilding the whole page.

This is where AJAX becomes useful.

In this example, I will show how to call a PL/SQL process from JavaScript using apex.server.process, pass a value to the server, update data in the database, and refresh only the affected region.

The example

Let's use a very simple Classic Report showing employees and their salaries.

When the user clicks a salary value, we want to:

  1. identify the employee,

  2. call a server-side PL/SQL process,

  3. double the employee's salary,

  4. return control to the browser,

  5. refresh the report.

There is no full page submit.

1. Make the report value clickable

Assume our Classic Report query returns:

  • EMPLOYEE_ID

  • SALARY

Instead of using an inline JavaScript handler, we can give the link a CSS class and store the employee ID in a data attribute.

In the HTML Expression of the Salary column:

<a href="#" class="js-salary" data-employee-id="#EMPLOYEE_ID#">#SALARY#</a>

The report now renders the salary as a clickable value.

The data-employee-id attribute contains the ID of the employee whose salary we want to update.

2. Create a Dynamic Action

Create a Dynamic Action with:

  • Event: Click

  • Selection Type: jQuery Selector

  • jQuery Selector: .js-salary

Because the report will later be refreshed, configure the event so that it also works for dynamically refreshed report rows.

For the True Action, choose Execute JavaScript Code.

Use:

const employeeId = this.triggeringElement.dataset.employeeId;

console.log("Employee ID:", employeeId);

apex.server.process(
    "PROC_SALARY",
    {
        x01: employeeId
    },
    {
        dataType: "text",

        success: function (pData) {
            console.log("Server response:", pData);
            apex.region("myREPORT").refresh();
        },

        error: function (jqXHR, textStatus, errorThrown) {
            apex.debug.error(
                "PROC_SALARY failed",
                textStatus,
                errorThrown
            );

            apex.message.alert("The salary update failed.");
        }
    }
);

The important part is:

apex.server.process("PROC_SALARY", ...)

This calls an APEX Ajax Callback named PROC_SALARY.

We pass the employee ID using:

x01: employeeId

On the server side, APEX exposes this value through:

apex_application.g_x01

3. Create the PL/SQL Ajax Callback

Create an Ajax Callback process named:

PROC_SALARY

The PL/SQL code can look like this:

begin
    update oehr_employees
       set salary = salary * 2
     where employee_id = to_number(apex_application.g_x01);

    commit;

    htp.p('ok');
exception
    when others then
        rollback;
        apex_debug.error('PROC_SALARY failed: %s', sqlerrm);
        raise;
end;

The value passed from JavaScript in x01 is available through:

apex_application.g_x01

We use it to identify the employee whose salary needs to be updated.

The callback sends a simple text response back to JavaScript:

htp.p('ok');

Because the JavaScript call specifies:

dataType: "text"

the returned value is available in the success function as pData.

4. Refresh only the report

If the server-side process completes successfully, we execute:

apex.region("myREPORT").refresh();

For this to work, set the Classic Report's Static ID to:

myREPORT

Only the report is refreshed.

The rest of the page remains unchanged.

The complete flow is therefore:

User clicks Salary
        ↓
Dynamic Action
        ↓
apex.server.process
        ↓
PROC_SALARY Ajax Callback
        ↓
UPDATE in Oracle Database
        ↓
Response returned to JavaScript
        ↓
Classic Report refresh

Why use AJAX?

The main advantage is that we do not need to submit and reload the entire page just to execute a small server-side operation.

This can provide a smoother user experience for operations such as:

  • changing a value,

  • executing a small PL/SQL operation,

  • validating data,

  • retrieving server-side information,

  • refreshing part of a page,

  • triggering business logic from a user action.

It also allows us to combine APEX's declarative development model with JavaScript when we need more control over the interaction.

What changed since the original 2023 version?

The core idea of the original article remains valid.

apex.server.process is still a useful way to call server-side APEX processes from JavaScript.

However, I would implement the client-side part differently today.

My original example used JavaScript directly inside the report link. In modern APEX applications, I prefer separating markup from behavior and using Dynamic Actions or dedicated JavaScript code instead.

This makes the application easier to understand, maintain and change later.

Error handling is another area worth making explicit.

A real application should not assume that every AJAX request succeeds. Both the client and server side should handle unexpected errors appropriately.

AJAX is not the same as background processing

There is also an important distinction.

Although the PL/SQL process executes without a full page submit, this is still a request-response operation.

The browser sends the AJAX request and waits for the server-side process to finish.

For short operations, this is exactly what we want.

For genuinely long-running tasks — imports, large calculations, integrations or batch processing — a real background execution mechanism is usually more appropriate.

That may involve APEX background processing capabilities or database mechanisms such as DBMS_SCHEDULER.

So the question is not simply:

How can I run PL/SQL in the background?

A better question is:

Does the user need to wait for the result, or should the work continue independently of the browser request?

That distinction becomes increasingly important as APEX applications grow from simple pages into larger enterprise systems.

Conclusion

One of the strengths of Oracle APEX is that we can start with declarative development and add lower-level control only where we actually need it.

apex.server.process provides a simple bridge between browser-side JavaScript and server-side PL/SQL.

For small interactive operations, it allows us to:

JavaScript → PL/SQL → Oracle Database → refresh only what changed

without submitting the whole page.

It is a small technique, but one I have used repeatedly in real APEX applications.

More from this blog

David Pataki

15 posts

Oracle ACE Pro, founder of Enrol Consulting, and Oracle Database and APEX developer with more than two decades of experience building data-driven business applications. I write about Oracle Database, APEX, cloud and AI-assisted development.