keepcalculator

06 Numbers and Powers

Mask Data in Oracle: Dynamic Data Masking Explained

Card No. 06·14005 · Updated · Standard formula, shown below

The calculator on this card is switched off while it is checked. The formula is below, and the worked example shows how to do the sum by hand.

Masking data in Oracle means replacing sensitive values (like credit card numbers, emails, or salaries) with realistic but fake ones so the data can be safely used in non-production environments or shown to users without full permissions. You do this either with Oracle’s built-in Dynamic Data Masking (part of Enterprise Manager and Advanced Security) or by writing your own masking logic with SQL and PL/SQL. This article covers both approaches, how they differ, and how to choose between them.

Formula

The masking formula above shows the core logic behind most simple data masking: keep a few characters at the start and end, and replace the middle with a repeated mask character. In words:

  • Masked value = first keep_start characters of the original + the mask character repeated (original length minus keep_start minus keep_end) times + last keep_end characters of the original.

Variables:

  • orig – the original string (text).
  • mask_char – the character used to replace the hidden part (often * or #).
  • keep_start – number of characters from the left to leave visible.
  • keep_end – number of characters from the right to leave visible.

This is a generic example; in real Oracle SQL you would use RPAD and SUBSTR to achieve the same effect.

Worked Example

Using the default values from the calculator: original 1234-5678-9012-3456, mask character *, keep 4 at the start and 4 at the end.

  1. Take the first 4 characters: 1234
  2. Count the middle characters to mask: length of original is 19 (including dashes). Subtract 4 (start) and 4 (end) = 11 characters to mask.
  3. Repeat the mask character 11 times: ***********
  4. Take the last 4 characters: 3456
  5. Concatenate: 1234***********3456

The calculator returns 1234***********3456, which matches the result you would get with the SQL expression shown below.

What Is Data Masking in Oracle?

Data masking (also called data obfuscation or anonymization) is the process of replacing original sensitive values with fictitious but structurally similar values. The goal is to keep the data useful for development, testing, or analytics while preventing unauthorized exposure of personal or confidential information.

Oracle offers two main masking strategies:

  • Static Data Masking – permanently alters a copy of the data (e.g., in a cloned database). The original database remains unchanged.
  • Dynamic Data Masking – masks data on the fly as it is returned to a user or application, without changing the underlying stored data. This is part of Oracle Advanced Security.

Dynamic masking is often preferred when you need to control what different users can see in the same production database. Static masking is used when you need to share data outside the organization or create safe test environments.

How to Mask Data with SQL and PL/SQL

If you do not have the Advanced Security option, you can implement masking manually. The simplest approach uses Oracle’s built-in string functions. Here is a common pattern for masking a credit card number, keeping the last four digits:

SELECT 
  SUBSTR(card_no, 1, 6) || 
  RPAD('*', LENGTH(card_no) - 10, '*') || 
  SUBSTR(card_no, -4) AS masked_card
FROM customers;

This keeps the first 6 and last 4 characters, replacing the middle with asterisks. For more complex rules (e.g., random replacement, preserving format), you can use DBMS_RANDOM to generate random letters or digits.

For example, to replace a digit with a random digit:

SELECT 
  REGEXP_REPLACE(
    phone,
    '[0-9]',
    FLOOR(DBMS_RANDOM.VALUE(0,10))
  ) AS masked_phone
FROM contacts;

Note that this replaces every digit with a random digit, which may not preserve the original pattern (e.g., area codes). For better fidelity, you can write a PL/SQL function that processes each character based on its type.

Oracle’s Built-in Dynamic Data Masking

Oracle Enterprise Manager (OEM) includes a Data Masking and Subsetting pack that provides a GUI to define masking formats. With Oracle Advanced Security, you can create masking policies on specific columns. The policy defines a transformation (e.g., random email, fixed format, or custom expression) and applies it to queries from users who lack the EXEMPT ACCESS POLICY privilege.

Key steps to set up dynamic masking using Oracle’s tools:

  1. Identify sensitive columns (e.g., SSN, credit card, email, salary).
  2. Define a masking format for each column (e.g., ‘XXX-XX-1234’ for SSN).
  3. Create a masking policy that maps the column to the format.
  4. Grant the policy to roles or users who should see masked data.
  5. Test with a user that has the policy applied.

This approach is transparent to applications – they receive masked data without any code changes. However, it requires the Advanced Security license, which is an extra cost on top of the Enterprise Edition.

Static Data Masking vs. Dynamic Data Masking

Choosing between static and dynamic masking depends on your use case:

  • Static masking – best for creating safe copies of data for development, testing, or outsourcing. The data is permanently altered, so there is no risk of accidental exposure. It is also useful when you need to share data with third parties.
  • Dynamic masking – best for production environments where you want to restrict what certain users see without duplicating the database. It is real-time, so the original data remains intact, but it can add a small performance overhead on queries.

A common misconception is that dynamic masking protects data at rest. It does not – it only protects data in transit to the client. If someone has direct access to the database files or can bypass the masking policy, they can see the original values. Therefore, dynamic masking should be combined with other security measures like encryption and access controls.

Common Problems and How to Avoid Them

Masking seems simple, but there are several pitfalls:

  • Format mismatch – if your masking replaces digits with letters or changes the length, downstream applications may break. Always preserve the original data type and length.
  • Referential integrity – if you mask a foreign key column, the masked value must still match the referenced primary key. Otherwise, joins will fail. Use consistent masking rules across related tables.
  • Uniqueness – if you mask a column that has a unique constraint, the masked values must also be unique. Random replacement can cause collisions. Use a deterministic function based on the original value (e.g., a hash) to ensure uniqueness.
  • Masking too little – if you leave too many characters visible (e.g., first 6 and last 4 of a credit card), an attacker might still be able to reconstruct the full number. Follow your organization’s data privacy guidelines.
  • Performance – dynamic masking on large tables can slow down queries. Test with realistic data volumes.

Another common issue is masking data in views or materialized views. If you create a view that selects from a masked column, the masking policy may not automatically apply to the view. You need to ensure the view inherits the policy or apply masking directly in the view definition.

Alternatives to Masking

Masking is not the only way to protect sensitive data. Alternatives include:

  • Encryption – transforms data into ciphertext that cannot be read without a key. Unlike masking, encrypted data is not usable for testing or analytics without decryption.
  • Redaction – Oracle’s DBMS_REDACT is a form of dynamic masking that is built into the database (no extra license for Enterprise Edition). It can redact data based on user policies, similar to Advanced Security’s masking.
  • Access control – simply restrict who can see the sensitive columns using views, VPD (Virtual Private Database), or column-level privileges. This does not alter the data, but prevents unauthorized access.
  • Tokenization – replaces sensitive data with a non-sensitive token that maps back to the original via a secure vault. This is common in payment systems.

For many use cases, Oracle’s built-in DBMS_REDACT is a free alternative to Advanced Security’s dynamic masking. It offers similar functionality and is available with Oracle Enterprise Edition.

Frequently Asked Questions

Does Oracle’s free edition support data masking?

Oracle Database Express Edition (XE) does not include Advanced Security or the Data Masking pack. However, you can still implement masking manually using SQL and PL/SQL functions, or use DBMS_REDACT if you are on Enterprise Edition (XE does not have DBMS_REDACT). For a completely free approach, write your own masking functions.

What is the difference between masking and redaction in Oracle?

Masking typically refers to replacing data with fake values (static or dynamic). Redaction (via DBMS_REDACT) is a specific feature that dynamically hides data from query results based on user policies. Redaction is a form of dynamic masking, but it is built into the database and does not require an extra license.

Can I mask data in a view without altering the base table?

Yes. You can create a view that applies masking functions to the sensitive columns. For example, CREATE VIEW v_customers AS SELECT id, mask_ssn(ssn) FROM customers;. This keeps the base table unchanged and only exposes masked data through the view.

How do I ensure masked values remain unique?

Use a deterministic masking function that always produces the same output for the same input. For example, use DBMS_CRYPTO.HASH to generate a hash and then convert it to a numeric or alphanumeric format. This ensures uniqueness if the original values are unique.

Does dynamic masking affect performance?

Yes, it can. Every query that accesses a masked column must run the masking transformation, which adds CPU and I/O overhead. The impact is usually small for simple formats, but can be significant for large data sets or complex expressions. Test with your actual workload.

Can I reverse masking to get the original data?

No, masking is meant to be irreversible. If you need to recover original values, keep a separate encrypted backup or use tokenization instead. Masking is a one-way transformation, which is why it is safe for sharing data.

Related

Formula used
in orig | Original value | - | 1234-5678-9012-3456 | 0
in mask_char | Mask character | - | * | 0
in keep_start | Digits to keep at start | - | 4 | 0 | 16
in keep_end | Digits to keep at end | - | 4 | 0 | 16
out masked | Masked value | - | substr(orig, 1, keep_start) || repeat(mask_char, max(0, length(orig) - keep_start - keep_end)) || substr(orig, length(orig) - keep_end + 1, keep_end) | 0

Each line is one input (in, sel, list) or one result (out: label, unit, formula, decimals). How the calculators work

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →