How to Redact Personal Data Before Calling an LLM in Oracle

Keep personal data out of prompts in Oracle AI Database 26ai with a redaction function, a call log, encrypted credentials, and tight network ACLs.

Every call to an AI provider sends part of your data across the line between your database and someone else's systems. Much of what a prompt carries is not needed: to classify a ticket or summarize a conversation, the model does not need the customer's phone number. Removing such details before the call keeps them out of the provider's systems and out of your own logs.

This guide shows how to see exactly what left the database, redact email addresses, card numbers, and phone numbers with a PL/SQL function, and check that the API key and network access are locked down, all in Oracle AI Database 26ai.

Code for This Guide

The examples are files 01 to 03 in the examples/ch27 folder of the Oracle AI code repository on GitHub, each with its output.

These examples come from AI Applications with Oracle Database 26ai and APEX 26.1, a book of 237 tested examples of AI in Oracle Database and APEX.

They read the LLM_CALLS log written by the GENERATE function from how to make LLM calls reliable in PL/SQL.

See What Left the Database

The first question of any review of an AI feature: what was sent, to whom, and how much? When every model call goes through one logging function, the log answers it.

Example:

-- everything GENERATE sent to a provider is in the log: how much, to which model
select model, count(*) as calls,
       round(sum(dbms_lob.getlength(prompt)) / 1024) as prompt_kb,
       min(called_at) as first_call
from   llm_calls
group  by model
order  by calls desc;

Output:

MODEL             CALLS    PROMPT_KB FIRST_CALL
______________ ________ ____________ _______________________
GEMINI              237          481 02-OCT-2026 07:41:52
LLAMA_LOCAL         134           90 02-OCT-2026 08:22:15
GEMINI_LITE          13            5 02-OCT-2026 07:49:25

Every prompt that went to Google is in the log, with its time: hundreds of calls and about half a megabyte of text for Gemini, plus the calls to a local model, which went nowhere. One central function for all model calls is a security measure, not only a convenience: it is the one place to log, to redact, and to block.

The log holds whatever the prompts held, ticket texts and customer names included, so it needs the same protection as the data: access limited to the people who investigate calls, and a retention period, such as a nightly DELETE FROM llm_calls WHERE called_at < SYSTIMESTAMP - INTERVAL '30' DAY.

Providers' terms differ and change. At the time of writing, Google's terms for the Gemini API say content sent on the paid tier is not used to improve its products, while content on the free tier may be. Read your provider's terms for your tier before sending real data.

Redact Before the Call

REDACT replaces email addresses, card numbers, and phone numbers with placeholders.

Example:

-- replaces e-mail addresses, card numbers, and phone numbers with placeholders
create or replace function redact (p_text in clob) return clob
is
  l_text clob := p_text;
begin
  l_text := regexp_replace(l_text,
              '[[:alnum:]._%+-]+@[[:alnum:].-]+\.[[:alpha:]]{2,}', '[e-mail]');
  l_text := regexp_replace(l_text,
              '\d{4}[ -]?\d{4}[ -]?\d{4}[ -]?\d{1,4}', '[card number]');
  l_text := regexp_replace(l_text,
              '\+?\d{1,3}[ .-]?\(?\d{2,4}\)?[ .-]?\d{3,4}[ .-]?\d{3,4}', '[phone]');
  return l_text;
end;
/

select redact('Please call me at +44 20 7946 0958 or write to '
              || 'olivia.walker@northwind.example. The charge was on card '
              || '4111 1111 1111 1111, on 3 March 2026.') as redacted
from   dual;

Output:

Function REDACT compiled

REDACTED
__________________________________________________________________________________________________
Please call me at [phone] or write to [e-mail]. The charge was on card [card number], on 3 March
2026.

The placeholders keep the sentence readable for the model, which still knows a phone number and a card were mentioned, and the date survives.

Where to call REDACTEffect
Inside the central GENERATE functionNo feature built on it can forget redaction.
In an APEX request handlerEvery AI call of the application is redacted, including assistants and agents.
Around individual promptsWorks, but each new feature must remember it.

Applying it in an APEX request handler is shown in how to intercept AI calls with request handlers in APEX.

Regular expressions catch only the patterns they are written for. Names and addresses need more, such as a list of the customer's own details to replace, and no method is complete. Send the least data a task needs. For masking data in query results shown to users, see mask sensitive data in Oracle APEX with Oracle Data Redaction (DBMS_REDACT).

Lock Down the Key and the Network

Two database features do quiet, important work:

  • The credential holds the API key encrypted. Code refers to it by name, and nobody can read the key back, not even the schema that owns it.
  • The network ACL allows connections only to the hosts the schema needs. Without an entry for a host, the schema cannot reach it, whatever its code tries.

Example:

-- the key is stored in the credential, encrypted; the dictionary shows its name only
select credential_name, username, enabled from user_credentials;

-- and the network access of the schema: one host for Gemini, one port for Ollama
select host, lower_port, upper_port, privilege from user_host_aces order by host;

Output:

CREDENTIAL_NAME    USERNAME    ENABLED
__________________ ___________ __________
GEMINI_CRED        NA          TRUE

HOST                                    LOWER_PORT    UPPER_PORT PRIVILEGE
____________________________________ _____________ _____________ ____________
generativelanguage.googleapis.com                                HTTP
host.docker.internal                         11434         11434 HTTP

The credential shows its name and nothing else. The ACL entries allow Gemini's host and Ollama's port, and code that tried to send data anywhere else would fail with ORA-24247. Keep ACLs to the hosts you use, change keys by dropping and recreating the credential, and give each application schema its own key so one can be revoked without the others. Setting both up is covered in how to call Gemini from Oracle Database with a stored credential.

Conclusion

Control what leaves Oracle Database by routing every model call through one logging function, protecting and expiring that log, and redacting email addresses, card numbers, and phone numbers before each prompt, ideally inside the central function or an APEX request handler. Keep the API key in an encrypted credential and limit network ACLs to the providers you use, and send only the data each task needs.

Vinish Kapoor
Vinish Kapoor

An Oracle ACE, author of four books on Oracle APEX, SQL and PL/SQL, and Oracle Forms, and a software developer building Oracle database applications since 2001.

guest

0 Comments
Oldest
Newest Most Voted
00