In this step-by-step guide, we’ll walk you through everything you need to know about Oracle Data Redaction. You’ll learn what data redaction is, how redaction policies work, the different types of data redaction, and how to implement it practically using SQL examples. By the end of this guide, you’ll understand how Oracle Data Redaction helps protect sensitive data in real time, ensures compliance with privacy laws, and strengthens your database security all without affecting your applications or data integrity.
What is Oracle Data Redaction?
Oracle Data Redaction is a built-in security feature in Oracle Database that helps protect sensitive or confidential information from unauthorized access. It works by masking or hiding data in real time when users query the database without changing the actual data stored in the tables.
For example, an HR manager might see a full employee salary, while a normal user only sees a masked value like “XXXXXX”. This ensures that critical data such as salary, PAN, credit card numbers, or personal details are never exposed to users who shouldn’t see them.
Oracle Data Redaction policies can be defined using the DBMS_REDACT package, allowing administrators to set rules based on conditions such as user roles, application contexts, or environments.
By using Data Redaction, organizations can strengthen database security, meet compliance standards (like GDPR or PCI DSS), and protect sensitive data all without modifying existing applications or database structures.
What is a Redaction Policy?
A Redaction Policy is the main rule or instruction that tells Oracle which data to hide, how to hide it, and when to hide it.
It acts as the control point for applying data masking to specific tables and columns.
Each policy defines:
- Table and Column: The data you want to protect (e.g., EMPLOYEE.SALARY).
- Redaction Type: How the data should be masked (Full, Partial, Random, etc.).
- Condition (Expression): When or for whom the masking should apply.
You create and manage redaction policies using the DBMS_REDACT package.
Oracle Data Redaction Types Explained (With Simple Examples)
1. FULL Redaction
Definition: Full redaction completely hides the original data and replaces it with a default masking value based on the data type.
Sample: 123-456-789 → XXXX
Best Use Case: When no part of the sensitive data should be visible.
2. PARTIAL Redaction
Definition: Partial redaction masks only a specific portion of the data and reveals the rest. You can customize which characters to expose.
Sample: 123456789 → 1234XXXX9
Best Use Case: Commonly used for masking credit card numbers, phone numbers, or showing only last 4 digits.
3. RANDOM Redaction
Definition: Random redaction replaces actual data with a random value each time. The output looks unpredictable and does not reveal real details.
Sample: 123456789 → 594837201
Best Use Case: When you want data to appear "changed" or obfuscated without showing the real value.
4. NULLIFY Redaction
Definition: NULLIFY replaces the actual data with NULL, making it appear blank to unauthorized users.
Sample: 123-456-789 → NULL
Best Use Case: When you want to completely hide data without showing any placeholder or masked text.
5. NONE
Definition: No redaction is applied. The data appears exactly as stored in the table.
Sample: 123456789 → 123456789
Best Use Case: For privileged users or when policy conditions evaluate to "no masking required."
6. REGEXP (Regular Expression) Redaction
Definition: REGEXP redaction masks data based on a regular expression pattern. Very useful for structured fields like email, PAN, Aadhaar, phone numbers, etc.
Sample: abc@gmail.com → ***@gmail.com
Best Use Case: Masking a specific format or pattern in a field.
Now we will explore how to create a data redaction policy and how to alter an existing policy for implementation on a database table.
Test Table:
SQL> select * from HR.INFO; SR_NO NAME CARD_INFO MAIL ---------- --------------- --------------- --------------- 1 Rahul Sharma 123-654-876 rahul@gmail.com 2 Amit Verma 987-321-654 amit@gmail.com 3 Sneha Patel 543-789-210 sneha@gmail.com 4 Karan Joshi 654-123-987 karan@gmail.com 5 Neha Kapoor 321-567-894 neha@gmail.com
Policy creation and management for each redaction type.
Policy Creation:
SQL> show user
USER is "SYS"
SQL>
SQL> BEGIN
DBMS_REDACT.ADD_POLICY (
object_schema => 'HR'
,object_name => 'INFO'
,policy_name => 'PROTECT_CARD'
,expression => '1=1');
END;
/ 2 3 4 5 6 7 8
PL/SQL procedure successfully completed.
Altering Policies for Each Redaction Type:
1. Redaction Type FULL:
SQL> BEGIN DBMS_REDACT.ALTER_POLICY( object_schema => 'HR', object_name => 'INFO', policy_name => 'PROTECT_CARD', action => DBMS_REDACT.ADD_COLUMN, column_name => 'CARD_INFO', function_type => DBMS_REDACT.FULL ); END; / 2 3 4 5 6 7 8 9 10 11 PL/SQL procedure successfully completed.
How the Table Appears to Users:
SQL> show user
USER is "TEST"
SQL> select * from HR.INFO;
SR_NO NAME CARD_INFO MAIL
---------- --------------- --------------- ---------------
1 Rahul Sharma rahul@gmail.com
2 Amit Verma amit@gmail.com
3 Sneha Patel sneha@gmail.com
4 Karan Joshi karan@gmail.com
5 Neha Kapoor neha@gmail.com
2. Redaction Type PARTIAL:
SQL> BEGIN DBMS_REDACT.ALTER_POLICY ( OBJECT_SCHEMA => 'HR' ,object_name => 'INFO' ,policy_name => 'PROTECT_CARD' ,action => DBMS_REDACT.MODIFY_COLUMN ,column_name => 'CARD_INFO' ,function_type => DBMS_REDACT.PARTIAL, function_parameters => 'vvvfvvvfvvv,vvv-vvv-vvv,#,4,6' ); END; / 2 3 4 5 6 7 8 9 10 11 12 PL/SQL procedure successfully completed.
How the Table Appears to Users:
SQL> show user
USER is "TEST"
SQL> select * from HR.INFO;
SR_NO NAME CARD_INFO MAIL
---------- --------------- --------------- ---------------
1 Rahul Sharma 123-###-876 rahul@gmail.com
2 Amit Verma 987-###-654 amit@gmail.com
3 Sneha Patel 543-###-210 sneha@gmail.com
4 Karan Joshi 654-###-987 karan@gmail.com
5 Neha Kapoor 321-###-894 neha@gmail.com
3. Redaction Type RANDOM:
SQL> BEGIN DBMS_REDACT.ALTER_POLICY( object_schema => 'HR', object_name => 'INFO', policy_name => 'PROTECT_CARD', action => DBMS_REDACT.MODIFY_COLUMN, column_name => 'CARD_INFO', function_type => DBMS_REDACT.RANDOM ); END; / 2 3 4 5 6 7 8 9 10 11 PL/SQL procedure successfully completed.
How the Table Appears to Users:
SQL> show user
USER is "TEST"
SQL> select * from HR.INFO;
SR_NO NAME CARD_INFO MAIL
---------- --------------- --------------- ---------------
1 Rahul Sharma XG;8(aZ;`OC rahul@gmail.com
2 Amit Verma 5U^5VkjO=]f amit@gmail.com
3 Sneha Patel )<"#8~m$1D* sneha@gmail.com
4 Karan Joshi sVT*GA&/{^\ karan@gmail.com
5 Neha Kapoor #XW3:MQp+`_ neha@gmail.com
4. Redaction Type NULLIFY:
SQL> BEGIN DBMS_REDACT.ALTER_POLICY( object_schema => 'HR', object_name => 'INFO', policy_name => 'PROTECT_CARD', action => DBMS_REDACT.MODIFY_COLUMN, column_name => 'CARD_INFO', function_type => DBMS_REDACT.NULLIFY ); END; / 2 3 4 5 6 7 8 9 10 11 PL/SQL procedure successfully completed.
How the Table Appears to Users:
SQL> show user
USER is "TEST"
SQL> select * from HR.INFO;
SR_NO NAME CARD_INFO MAIL
---------- --------------- --------------- ---------------
1 Rahul Sharma rahul@gmail.com
2 Amit Verma amit@gmail.com
3 Sneha Patel sneha@gmail.com
4 Karan Joshi karan@gmail.com
5 Neha Kapoor neha@gmail.com
5. Redaction Type NONE:
SQL> BEGIN DBMS_REDACT.ALTER_POLICY( object_schema => 'HR', object_name => 'INFO', policy_name => 'PROTECT_CARD', action => DBMS_REDACT.MODIFY_COLUMN, column_name => 'CARD_INFO', function_type => DBMS_REDACT.NONE ); END; / 2 3 4 5 6 7 8 9 10 11 PL/SQL procedure successfully completed.
How the Table Appears to Users:
SQL> show user
USER is "TEST"
SQL> select * from HR.INFO;
SR_NO NAME CARD_INFO MAIL
---------- --------------- --------------- ---------------
1 Rahul Sharma 123-654-876 rahul@gmail.com
2 Amit Verma 987-321-654 amit@gmail.com
3 Sneha Patel 543-789-210 sneha@gmail.com
4 Karan Joshi 654-123-987 karan@gmail.com
5 Neha Kapoor 321-567-894 neha@gmail.com
6. Redaction Type REGEXP:
SQL> BEGIN DBMS_REDACT.ALTER_POLICY( object_schema => 'HR', object_name => 'INFO', policy_name => 'PROTECT_CARD', action => DBMS_REDACT.ADD_COLUMN, column_name => 'MAIL', function_type => DBMS_REDACT.REGEXP, regexp_pattern => '^[^@]+', regexp_replace_string => '***' ); END; / 2 3 4 5 6 7 8 9 10 11 12 13 PL/SQL procedure successfully completed.
How the Table Appears to Users:
SQL> show user
USER is "TEST"
SQL> select * from HR.INFO;
SR_NO NAME CARD_INFO MAIL
---------- --------------- --------------- ---------------
1 Rahul Sharma 123-654-876 ***@gmail.com
2 Amit Verma 987-321-654 ***@gmail.com
3 Sneha Patel 543-789-210 ***@gmail.com
4 Karan Joshi 654-123-987 ***@gmail.com
5 Neha Kapoor 321-567-894 ***@gmail.com
Note: Once a redaction policy is applied to a table, even the table owner cannot view the original data in the redacted column.
Next, we will learn how to grant access so a specific user can view the original data in a redacted column.
SQL> show user USER is "HR" SQL> SQL> select * from HR.INFO; SR_NO NAME CARD_INFO MAIL ---------- --------------- --------------- --------------- 1 Rahul Sharma 123-654-876 ***@gmail.com 2 Amit Verma 987-321-654 ***@gmail.com 3 Sneha Patel 543-789-210 ***@gmail.com 4 Karan Joshi 654-123-987 ***@gmail.com 5 Neha Kapoor 321-567-894 ***@gmail.com
As you can see, even the HR schema cannot view the 'MAIL' column in its own 'INFO' table. Now, we will grant access to the HR schema to view this redacted column by altering the existing policy.
SQL> show user USER is "SYS" SQL> SQL> BEGIN DBMS_REDACT.ALTER_POLICY ( OBJECT_SCHEMA => 'HR', object_name => 'INFO', policy_name => 'PROTECT_CARD', action => DBMS_REDACT.MODIFY_EXPRESSION, expression => 'sys_context(''userenv'',''session_user'') != ''HR''' ); END; / 2 3 4 5 6 7 8 9 10 PL/SQL procedure successfully completed.
After altering the policy, the HR schema can now view the original values in the column.
SQL> show user USER is "HR" SQL> SQL> select * from HR.INFO; SR_NO NAME CARD_INFO MAIL ---------- --------------- --------------- --------------- 1 Rahul Sharma 123-654-876 rahul@gmail.com 2 Amit Verma 987-321-654 amit@gmail.com 3 Sneha Patel 543-789-210 sneha@gmail.com 4 Karan Joshi 654-123-987 karan@gmail.com 5 Neha Kapoor 321-567-894 neha@gmail.com
How to Delete an Existing Redaction Policy
SQL> show user USER is "SYS" SQL> SQL> BEGIN DBMS_REDACT.DROP_POLICY ( OBJECT_SCHEMA => 'HR', object_name => 'INFO', policy_name => 'PROTECT_CARD'); END; / 2 3 4 5 6 7 PL/SQL procedure successfully completed.
Conclusion: With the right redaction policies in place, Oracle Data Redaction offers a powerful and flexible way to secure sensitive columns, mask confidential information, and control data exposure for different users across your database.
