1. What is an Oracle SQL Patch?
An Oracle SQL Patch is a mechanism that allows DBAs to inject optimizer hints into a SQL statement without changing application code.
It is mainly used when:
- A SQL statement suddenly performs badly
- You cannot modify the SQL in the application
- You want a safe, reversible tuning fix
Unlike SQL Profiles or SQL Plan Baselines, SQL Patches are lighter and more targeted.
2. Why SQL Patch is Used
Problems SQL Patch Solves
- Bad execution plans after statistics refresh
- Wrong join methods (HASH JOIN instead of NESTED LOOP)
- Missing index usage
- Performance regression after upgrade or patching
Why Not Change SQL Code?
- Application owned by vendor
- Code deployed in production and change is risky
- Same SQL used at multiple places
✅ SQL Patch fixes performance without touching code
3. SQL Patch vs Other Tuning Options
| Feature | SQL Patch | SQL Profile | SQL Baseline |
|---|---|---|---|
| Inject hints | ✅ Yes | ❌ No | ❌ No |
| Code change needed | ❌ No | ❌ No | ❌ No |
| Force plan | ❌ Partial | ❌ No | ✅ Yes |
| Easy rollback | ✅ Yes | ⚠️ Moderate | ⚠️ Moderate |
| Best for | Quick fix | Stats issues | Stable plans |
4. Important Prerequisites
Before creating a SQL Patch:
- SQL text must be exactly the same
- SQL should be parseable
- Required indexes must already exist
- User must have privileges:
GRANT ADMINISTER SQL MANAGEMENT OBJECT TO <user>;5. How SQL Patch Works (Internals)
- Oracle matches the SQL text
- Injects hints at parse time
- Optimizer generates a new execution plan
- No plan is forced — optimizer still decides
6. SQL Patch Creation Methods by Version
Oracle 12.1
Uses internal package
SYS.DBMS_SQLDIAG_INTERNAL.I_CREATE_PATCHOracle 12.2 and Above
Uses public supported package
SYS.DBMS_SQLDIAG.CREATE_SQL_PATCH7. Step-by-Step SQL Patch Creation (Oracle 12.1)
Step 1: Identify Problem SQL
SELECT sql_id, sql_text
FROM v$sql
WHERE sql_text LIKE '%employees%';
Step 2: Decide Required Hint
Example: Force index usage
INDEX(employees emp_idx1)Step 3: Create SQL Patch
BEGIN SYS.DBMS_SQLDIAG_INTERNAL.I_CREATE_PATCH( sql_text => 'SELECT * FROM employees WHERE department_id = 10', hint_text => 'INDEX(employees emp_idx1)', name => 'EMP_DEPT_INDEX_PATCH', description => 'Force index usage for employee query' );END;/Step 4: Flush Shared Pool (Optional)
ALTER SYSTEM FLUSH SHARED_POOL;8. Step-by-Step SQL Patch Creation (Oracle 12.2+)
Step 1: Identify SQL
SELECT sql_id, sql_textFROM v$sqlWHERE sql_id = 'abc123xyz';Step 2: Create SQL Patch
BEGIN DBMS_SQLDIAG.CREATE_SQL_PATCH( sql_text => 'SELECT * FROM employees WHERE department_id = 10', hint_text => 'INDEX(employees emp_idx1)', name => 'EMP_DEPT_INDEX_PATCH' );END;/9. Example: Fixing a Slow Query
Problem Query
SELECT *FROM ordersWHERE customer_id = 100;Issue
- Full table scan on ORDERS
- ORDERS table is large
- Index exists:
ORDERS_CUST_IDX
Solution: SQL Patch
BEGIN DBMS_SQLDIAG.CREATE_SQL_PATCH( sql_text => 'SELECT * FROM orders WHERE customer_id = 100', hint_text => 'INDEX(orders ORDERS_CUST_IDX)', name => 'ORDERS_CUST_PATCH' );END;/Result
- Optimizer now uses index
- Query response time improves significantly
- No application change needed
10. Verify SQL Patch
List SQL Patches
SELECT name, status, descriptionFROM dba_sql_patches;Check Applied Hints
SELECT *FROM v$sqlWHERE sql_id = '<sql_id>';Look for hint usage in execution plan.
11. Disable or Drop SQL Patch (Rollback)
Disable Patch
EXEC DBMS_SQLDIAG.ALTER_SQL_PATCH( name => 'ORDERS_CUST_PATCH', attribute_name => 'STATUS', value => 'DISABLED');Drop Patch
EXEC DBMS_SQLDIAG.DROP_SQL_PATCH('ORDERS_CUST_PATCH');When NOT to Use SQL Patch
❌ If SQL text changes frequently
❌ If plan stability is required → use SQL Baseline
❌ If problem is missing statistics → gather stats first