An Oracle to Databricks migration moves an Oracle data warehouse, its PL/SQL and ODI pipelines, schedulers, and reports onto Delta Lake tables and Lakeflow pipelines, while core OLTP databases usually stay on Oracle. It is a re-architecture: the risk sits in PL/SQL logic and in behavior differences such as empty strings treated as NULL, DATE values that carry a time, and NUMBER precision, not in the data copy. Databricks' Lakebridge (through BladeBridge) converts Oracle SQL and PL/SQL, and the Lakeflow Connect Oracle connector can stream changes through LogMiner (still Beta and not supported on Oracle RAC), but engineers must refactor the logic and reconcile every figure before cutover. Oracle 19c Premier Support runs to December 31, 2029, so the case for moving rests on cost, flexibility, and AI workloads, not a support deadline.
Oracle still anchors the enterprise data warehouse for many organizations, often with fifteen years of PL/SQL packages, ODI mappings, and scheduler jobs behind it. This page covers what moves and what stays, how to choose a strategy, how each Oracle component maps to Databricks, what the conversion tools and the CDC connector can and cannot do, and where results quietly drift. For the services side, see our Databricks migration services overview, and for every legacy ETL tool at once, our ETL migration to Databricks article.
Unlike an older SQL Server release, Oracle 19c has a long runway, so the business case has to stand on its own merits:
| Oracle Release | Premier Support Ends | Extended Support Ends |
|---|---|---|
| 19c (long-term release) | December 31, 2029 | December 31, 2032 |
| 21c (innovation release) | July 2027 | Not listed |
| 26ai (formerly 23ai, long-term release) | December 31, 2031 | To be announced |
These dates come from trackers that mirror Oracle's Lifetime Support Policy, checked in October 2026, so confirm yours with Oracle. The pressures that usually drive a move are these:
For analytics, yes. For core transactions, Databricks' own guidance says Oracle or a dedicated OLTP database remains the right choice:
| Oracle Workload | Where It Lands | Notes |
|---|---|---|
| Data warehouse and marts (Exadata or otherwise) | Delta Lake on Databricks | The core use case |
| ETL: ODI mappings and PL/SQL batch loads | Lakeflow pipelines and jobs | Rebuilt, not copied |
| Reporting and BI | Databricks SQL with BI tools on top | OBIEE and BI Publisher content must be repointed or migrated |
| Core OLTP (ERP, banking, order management) | Stays on Oracle or a dedicated OLTP database | Mission-critical, latency-sensitive systems |
| New operational applications | Lakebase, Databricks' managed Postgres database, generally available since January 2026 | Not positioned as a replacement for Oracle's core OLTP engine |
Most teams therefore stream changes from Oracle into the lakehouse and retire only the analytical workloads. Reports follow the data, so plan OBIEE to Power BI and Oracle BI Publisher to Power BI moves in the same wave as their source tables, and see our Power BI consulting services and reports conversion work for the report layer.
Two sequencing patterns are common, and the right one depends on how soon the business needs visible results:
| Approach | What Happens First | Strength | Trade-off |
|---|---|---|---|
| ETL first | Ingest Oracle into a bronze layer, clean into silver, and serve from gold | Modern pipelines and lineage from the start | Slower to show business value |
| BI first | Lift existing marts into the gold layer and repoint reporting | Fast query gains and visible results for users | Backend ETL still has to be modernized afterward |
Many programs blend the two: start with a visible reporting workload, then modernize its pipeline in the same wave. Whichever you choose, our key checklist for BI modernization and our overview of data warehouse to Databricks migration cover how to sequence the waves.
| Layer | What It Includes | Commonly Missed |
|---|---|---|
| Data and storage | Schemas, data types, partitions, indexes, and history | How much history genuinely needs to move |
| Procedural logic | PL/SQL packages, procedures, functions, triggers, views, and materialized views | Package-level state and dynamic SQL |
| Pipelines and orchestration | ODI mappings and load plans, DBMS_SCHEDULER chains, shell scripts, and file feeds | Database links and UTL_FILE exports that feed other systems |
| Security and governance | Roles, grants, Virtual Private Database policies, and data masking | VPD predicates that must be rebuilt in Unity Catalog |
| Consumers | OBIEE, BI Publisher, Oracle Reports, extracts, APIs, and applications | Consumers nobody documented |
| Oracle Component | Common Challenge | How to Solve It |
|---|---|---|
| PL/SQL packages and procedures | Thousands of objects with package-level state, cursor loops, dynamic SQL, and exception handling that has no direct Spark equivalent | Build a dependency graph, convert in waves by complexity, and refactor row-by-row logic into set-based SQL, as in our PL/SQL conversion article; SQL scripting covers simpler procedural needs |
| Triggers | Audit and defaulting logic fires implicitly on every insert or update | Move the logic into explicit pipeline steps, and use pipeline expectations for data quality rules |
| Sequences | Surrogate keys come from sequences | Use identity columns or generated keys, and test key behavior in parallel runs |
| Database links, UTL_FILE, and DBMS_ packages | Cross-database reads and file exports hide dependencies | Replace links with Lakehouse Federation or ingestion, file handling with Volumes and Auto Loader, and scheduler calls with Lakeflow Jobs |
| ODI and OWB mappings | Knowledge modules and load plans embed logic in proprietary metadata | Extract mappings, rebuild as Lakeflow Spark Declarative Pipelines, and recreate load-plan dependencies in Lakeflow Jobs, as in our ODI migration article |
| DBMS_SCHEDULER, cron, and shell jobs | Chains mix SQL, shell, and file triggers with email alerts | Consolidate into Lakeflow Jobs with explicit dependencies, retries, and notifications |
| GoldenGate and LogMiner CDC | Keeping both platforms in sync without heavy source load | Use the Lakeflow Connect Oracle connector where its limits allow, and otherwise GoldenGate or a partner tool |
| Partitions, indexes, and hints | Queries tuned with B-tree and bitmap indexes lose their performance profile | Use liquid clustering and data skipping, drop hints, and benchmark top queries |
| Security (roles, VPD, masking) | Row-level policies and fine-grained grants do not carry over | Redesign access with Unity Catalog groups, row filters, and column masks, and see our guide to migrating row-level security |
| Oracle | Databricks SQL | Watch For |
|---|---|---|
| ROWNUM <= 10 | LIMIT 10, or row_number() when ranking | ROWNUM is applied before ORDER BY, so results can differ |
| NVL(a, b) | coalesce(a, b) | None for the two-argument form |
| DECODE(x, 1, 'A', 'B') | CASE WHEN x = 1 THEN 'A' ELSE 'B' END | DECODE treats two NULLs as equal, and CASE does not |
| SYSDATE | current_timestamp() | SYSDATE returns a DATE with a time part |
| CONNECT BY ... START WITH | WITH RECURSIVE | Recursive CTEs are generally available on Databricks |
| sequence.NEXTVAL | Identity column or generated key | Gaps and ordering can differ |
| Outer join (+) syntax | ANSI LEFT or RIGHT JOIN | Rewrite carefully because filters change meaning |
| FROM DUAL | Omit the FROM clause | None |
| Oracle | Databricks | Watch For |
|---|---|---|
| NUMBER(p,s) | DECIMAL(p,s) | Match precision and scale exactly |
| NUMBER with no precision | DECIMAL or DOUBLE, chosen per column | Profile real values before choosing |
| DATE | TIMESTAMP | Oracle DATE carries a time part |
| TIMESTAMP WITH TIME ZONE | TIMESTAMP | Decide how time zones are normalized |
| VARCHAR2 and CHAR | STRING | Byte versus character length, and CHAR padding |
| CLOB and BLOB | STRING and BINARY | Large objects need storage and volume planning |
Lakebridge is Databricks' free, open-source migration toolkit from Databricks Labs, and Databricks states it can automate up to 80% of migration tasks, a vendor figure for favorable cases. For Oracle, the pieces differ from the SQL Server story:
| Tool | What It Does for Oracle | Status and Limits |
|---|---|---|
| Analyzer and Oracle profiler | Inventories objects and scores complexity | Oracle is a supported profiler source in recent Lakebridge releases |
| BladeBridge | Converts Oracle SQL and PL/SQL into Databricks SQL with rule-based transpilation | Complex packages, dynamic SQL, and package state need manual work |
| Lakebridge Agentic Converter | A Genie Code-powered converter that translates Oracle SQL, among other dialects, into ANSI SQL and retries failed sections | Beta, and a workspace admin must enable it |
| Switch (LLM-based) | An experimental option for constructs the other tools do not cover | Output needs review because it is LLM-generated |
| Partner accelerators | AI-assisted PL/SQL conversion offered by Databricks partners, often with high automation claims | Treat claims as vendor figures and ask for a pilot on your own code |
Morpheus, Lakebridge's deterministic SQL transpiler, covers SQL Server, Snowflake, and Synapse but not Oracle, so Oracle conversion relies on BladeBridge, the agentic converter, or Switch. Lakebridge is a Databricks Labs project, so confirm support terms before you build production timelines on it. Our Databricks migration services overview covers how tooling and services divide the work, and our SQL Server and SSIS and Teradata articles show how the same tools behave on other sources.
A phased data path avoids a big-bang copy:
The connector's documented requirements and limits decide whether step 3 works for your estate:
| Requirement or Limit | Detail |
|---|---|
| Status | Beta, so confirm current status before production use |
| Oracle versions | 12c and above, including 19c, 21c, 23ai, and 26ai |
| Source setup | Archive log mode, supplemental logging (primary-key level at minimum), and archive logs retained for at least 48 hours |
| Not supported | Oracle RAC, physical standby, Autonomous Database, multi-tenant Amazon RDS for Oracle, and encrypted data with a closed wallet |
| Skipped tables | LogMiner ignores tables with unsupported types or attributes, such as BFILE, nested tables, and identity columns |
| Name length | Table and column names must not exceed 30 characters |
| Output | Raw data only, with transformations done downstream in pipelines |
| Where it runs | RDS for Oracle (single-tenant), Oracle on EC2, Azure VMs, or OCI, and on-premises over ExpressRoute, Direct Connect, or VPN |
Many Exadata estates run RAC, so check that limit early and plan GoldenGate or a partner tool where the connector does not apply.
| Phase | Oracle-Specific Work | Exit Criterion |
|---|---|---|
| Discovery | Run the Analyzer and Oracle profiler, and inventory PL/SQL, ODI, scheduler jobs, database links, and consumers | A scored inventory |
| Rationalization | Retire unused schemas, packages, and reports, and decide how much history moves | An approved, smaller scope |
| Target design | Define the medallion layers, Unity Catalog structure, and identity mapping, and choose ETL first or BI first | A signed-off design and wave plan |
| Pilot | Migrate one visible, low-risk workload end to end | A measured automation rate and reconciled output |
| Data and CDC | Bulk-load history and set up CDC within the connector's limits or with an alternative | Databricks current within the agreed latency |
| Code conversion | Convert PL/SQL, ODI mappings, and jobs, and refactor cursor logic into set-based SQL | Converted code passing tests |
| Parallel run and cutover | Reconcile through a month-end, repoint reporting, and retire Oracle workloads and licenses | Signed-off parity |
A daily load that loops over regions and merges one row at a time is typical Oracle code. This is an illustrative example, not a client engagement.
CREATE OR REPLACE PROCEDURE load_sales_summary (p_date IN DATE) AS
BEGIN
FOR r IN (SELECT region_id, SUM(amount) AS total
FROM sales
WHERE TRUNC(sale_date) = p_date
GROUP BY region_id) LOOP
MERGE INTO sales_summary s
USING (SELECT r.region_id AS rid, r.total AS amt FROM dual) src
ON (s.region_id = src.rid AND s.sale_date = p_date)
WHEN MATCHED THEN
UPDATE SET s.total = src.amt
WHEN NOT MATCHED THEN
INSERT (region_id, sale_date, total)
VALUES (src.rid, p_date, src.amt);
END LOOP;
COMMIT;
END;
/
MERGE INTO gold.sales_summary AS s
USING (
SELECT region_id,
CAST(:p_date AS DATE) AS summary_date,
SUM(amount) AS total
FROM silver.sales
WHERE CAST(sale_date AS DATE) = CAST(:p_date AS DATE)
GROUP BY region_id
) AS src
ON s.region_id = src.region_id AND s.sale_date = src.summary_date
WHEN MATCHED THEN
UPDATE SET s.total = src.total
WHEN NOT MATCHED THEN
INSERT (region_id, sale_date, total)
VALUES (src.region_id, src.summary_date, src.total);
The loop disappears: one aggregation feeds one MERGE, and Spark parallelizes the work across the cluster. Two details matter. TRUNC(sale_date) in Oracle removes the time part of a DATE, so the Databricks version casts the TIMESTAMP to a DATE, and a missed cast would silently drop most of a day's rows. The MERGE is also safe to re-run because it overwrites the day's total instead of adding to it, which you want to preserve. Please test this example in a Databricks workspace before adapting it.
| Oracle Behavior | What Changes on Databricks | Safeguard |
|---|---|---|
| Empty string is stored as NULL | An empty string and NULL are different values, so filters, joins, and counts change | Decide the rule deliberately, and convert empty strings to NULL where the old behavior must hold |
| DATE carries a time part | Comparisons and groupings by day change if the type or cast is wrong | Map DATE to TIMESTAMP and cast explicitly when comparing by day |
| NUMBER without precision | Mapped types can round or overflow values | Profile real data and choose DECIMAL or DOUBLE per column |
| NLS settings for date format, sort order, and comparison | Results that depended on session settings may change | Inventory NLS dependencies and make rules explicit in code |
| ROWNUM is assigned before ORDER BY | Top-N queries can return different rows | Rewrite with row_number() and an explicit ordering |
| CHAR is blank-padded | Padded values may compare differently as STRING | Trim keys explicitly and test with real data |
These are the differences behind totals that never quite reconcile, and the reason for column-level checks like those in our automated ETL testing with Python approach. The same set-based thinking appears in our comparison of traditional vs modern ETL.
Without indexes and hints, performance comes from data layout and compute choices:
| Oracle Mechanism | Databricks Approach |
|---|---|
| B-tree and bitmap indexes | Liquid clustering and data skipping on Delta tables |
| Table partitioning | Liquid clustering for most tables, with partitioning reserved for very large ones |
| Optimizer hints | Drop them, and benchmark the top queries before cutover |
| Materialized views | Databricks materialized views or pipeline tables, depending on refresh needs |
| Exadata smart scans and parallel query | Photon and right-sized compute, governed by cluster policies |
Set cluster policies, auto-termination, and budget alerts from day one, because consumption-based billing rewards governance and punishes drift. Our articles on Databricks vs Snowflake and cloud migration to Databricks cover platform and cost trade-offs in more depth.
Moving an Oracle warehouse is easy to start and hard to finish because the effort hides in PL/SQL, ODI pipelines, and the numbers that must still match. DataTerrain brings 17+ years and 400+ clients in data and reporting modernization, including Oracle-centered estates, with automated assessment, PL/SQL and ETL conversion, and figure-for-figure validation. Start with our ETL Solutions or the wider Databricks migration services page.
Databricks Migration Services | SQL Server and SSIS to Databricks | Teradata to Databricks Migration | ETL Migration to Databricks | Data Warehouse to Databricks | Legacy Systems to Databricks | Data Platform Migration to Databricks | Cloud Migration to Databricks | Informatica to Databricks Migration | Oracle Data Integrator ETL | Oracle to Microsoft Fabric Migration | Oracle Data Integrator vs Informatica | OBIEE to Power BI Migration | Oracle BI Publisher to Power BI