Atlas Case Studies How we work Book a demo

Hard sources — not covered by free tools

Also parsed — certify what free tools miss

Campaign

Warehouses

Runtimes

Convert Oracle PL/SQL to BigQuery SQL

Stored procedures, packages, functions, and triggers parsed structurally. Converted to BigQuery SQL procedures and scripting. 2,000+ built-in function mappings, full lineage, validated parity.

Architecture

Oracle PL/SQL in. Google Cloud out.

Deterministic parsers read the estate and emit native Google Cloud code — not PL/SQL wrapped in a compatibility layer.

Oracle PL/SQL → MigryX parser → BigQuery + Dataform + Composer

Oracle PL/SQL
PackagesProcs + funcs
Cursor loopsRow-by-row
CONNECT BYHierarchies
BULK COLLECT%ROWTYPE
MigryX Parser
Deterministic parseAI optional
Row-level parityBefore cutover
SQLX emitDataform models
DAG emitComposer
Google Cloud
BigQuerySet-based SQL
DataformGoverned models
Cloud ComposerReplaces scheduler
Cloud FunctionsNon-SQL tools
IAM + CLSLeast privilege
Git reposReproducible packs

AI is an optional add-on, off by default — the conversion runs end to end without it, air-gapped if your estate requires it.

Why BigQuery

Oracle procedural logic becomes serverless analytics

PL/SQL procedures become BigQuery scripting

BigQuery scripting supports DECLARE, SET, IF/ELSE, LOOP, and exception handling. MigryX maps Oracle's procedural blocks to BigQuery's BEGIN...EXCEPTION...END structure. Temporary tables replace PL/SQL collections. 280 packages converted in a single engagement.

CONNECT BY becomes recursive CTE natively

BigQuery has first-class support for recursive CTEs with WITH RECURSIVE syntax. MigryX converts Oracle's START WITH...CONNECT BY PRIOR hierarchical queries preserving LEVEL semantics, path construction, and cycle detection -- no workarounds needed.

Oracle types become BigQuery native types

Oracle NUMBER, VARCHAR2, DATE, CLOB, and collection types map to BigQuery INT64, STRING, DATETIME, STRING, and ARRAY/STRUCT. MigryX handles precision mapping, implicit type coercion, and Oracle-specific NULL semantics that differ in BigQuery.

Parser output

Oracle PL/SQL procedure to BigQuery SQL procedure

A PL/SQL procedure with cursor processing, DECODE, and Oracle date functions -- converted to a BigQuery SQL procedure with scripting, CASE WHEN, and native date handling.

Oracle PL/SQL
-- Procedure: refresh_department_metrics
CREATE OR REPLACE PROCEDURE refresh_metrics AS
  v_count NUMBER := 0;
  CURSOR c_depts IS
    SELECT department_id,
      NVL(department_name, 'Unassigned'),
      DECODE(status, 'A', 'Active',
        'I', 'Inactive', 'Unknown')
    FROM departments
    WHERE create_date >=
      ADD_MONTHS(SYSDATE, -6);
BEGIN
  FOR rec IN c_depts LOOP
    INSERT INTO dept_metrics (
      dept_id, dept_name, status_label,
      headcount, run_date
    )
    SELECT rec.department_id,
      rec.department_name,
      rec.status,
      COUNT(*),
      SYSDATE
    FROM employees e
    WHERE e.dept_id = rec.department_id;

    v_count := v_count + 1;
  END LOOP;

  DBMS_OUTPUT.PUT_LINE(
    'Processed: ' || TO_CHAR(v_count));
  COMMIT;
EXCEPTION
  WHEN OTHERS THEN
    ROLLBACK;
    RAISE;
END;
MigryX
converts
BigQuery SQL
-- PL/SQL procedure → BigQuery SQL
CREATE OR REPLACE PROCEDURE
  dataset.refresh_metrics()
BEGIN
  DECLARE v_count INT64 DEFAULT 0;

  INSERT INTO dataset.dept_metrics
    (dept_id, dept_name, status_label,
     headcount, run_date)
  SELECT
    d.department_id,
    COALESCE(d.department_name,
             'Unassigned'),
    CASE d.status
      WHEN 'A' THEN 'Active'
      WHEN 'I' THEN 'Inactive'
      ELSE 'Unknown'
    END AS status_label,
    COUNT(e.employee_id) AS headcount,
    CURRENT_DATE() AS run_date
  FROM dataset.departments d
  LEFT JOIN dataset.employees e
    ON e.dept_id = d.department_id
  WHERE d.create_date >=
    DATE_SUB(CURRENT_DATE(),
             INTERVAL 6 MONTH)
  GROUP BY d.department_id,
    d.department_name, d.status;

  SET v_count = (
    SELECT COUNT(DISTINCT dept_id)
    FROM dataset.dept_metrics
    WHERE run_date = CURRENT_DATE());

EXCEPTION WHEN ERROR THEN
  SELECT @@error.message;
END;

Cursor FOR loop replaced with set-based INSERT...SELECT with GROUP BY. DECODE mapped to CASE WHEN. NVL mapped to COALESCE. ADD_MONTHS mapped to DATE_SUB with INTERVAL. SYSDATE mapped to CURRENT_DATE(). Row-by-row processing eliminated.

Coverage

Oracle PL/SQL to BigQuery — artifact mapping

Oracle PL/SQL Component BigQuery Equivalent Notes
Stored ProcedureBigQuery SQL procedureBEGIN/EXCEPTION scripting structure
Package (spec + body)Dataset + routinesPackage functions become individual routines
FunctionBigQuery UDF (SQL or JS)Scalar and table-valued functions
CONNECT BY hierarchical queryWITH RECURSIVE CTENative recursive CTE support
DECODECASE WHENMulti-branch DECODE fully expanded
NVL / NVL2COALESCE() / IF()NVL2 mapped to IF with null check
TriggerScheduled query + Cloud FunctionEvent-driven logic via Pub/Sub
SequenceGENERATE_UUID() / ROW_NUMBER()Identity generation patterns mapped
Materialized ViewBigQuery Materialized ViewDirect equivalent with auto-refresh
DBMS_SCHEDULERBigQuery scheduled queryCron-based scheduling, Cloud Scheduler
EXECUTE IMMEDIATEEXECUTE IMMEDIATEDirect equivalent in BigQuery scripting
Cursor FOR loopFOR...IN (SELECT ...) / set-based SQLRow iteration or set-based conversion
Database LinkBigQuery connection / federated queryCross-source access via BigLake
Collections (TABLE/VARRAY)ARRAY / STRUCTNested types mapped to BigQuery native
Validation

Every conversion validated to row-level parity

Data Matching compares Oracle output against BigQuery output -- row by row, column by column. In the case study below, all stored procedure results were validated with full production backtesting against the original Oracle database.

See how Data Matching works →
3,800
PL/SQL objects modernized
2,000+
Function mappings
280
Packages converted

Government Agency: Oracle PL/SQL to BigQuery in 15 Months

3,800 PL/SQL objects converted to BigQuery SQL procedures and UDFs. 280 packages decomposed into BigQuery routines organized by dataset. CONNECT BY hierarchical queries rewritten as recursive CTEs. DECODE/NVL patterns mapped to CASE WHEN/COALESCE. Oracle license costs eliminated, serverless compute enabled zero-infrastructure operations.

Explore migration case studies →

What to bring to a Oracle PL/SQL assessment

Review a representative sample with us →

Explore other modernizations

Targets: Snowflake Databricks Google Cloud Azure AWS PySpark Polars Iceberg DBT SQLMesh
Sources: SAS Alteryx Talend Qlik DataStage Informatica COBOL Oracle Teradata SSIS