Migrating from Oracle to HeliosDB
Migrating from Oracle to HeliosDB
Last Updated: November 11, 2025 Target Audience: Database Administrators, Oracle DBAs, Architects Estimated Migration Time: 4-12 weeks depending on complexity Difficulty: Advanced
Table of Contents
- Overview
- Why Migrate to HeliosDB?
- Compatibility Assessment
- Prerequisites
- Migration Strategies
- Step-by-Step Migration
- Feature Mapping
- PL/SQL Migration
- DBMS Package Usage
- Performance Tuning
- Troubleshooting
- Best Practices
- Rollback Plan
- Case Studies
- Next Steps
Overview
HeliosDB provides 55% Oracle 23ai compatibility, supporting core SQL features, PL/SQL procedures, and 19 DBMS packages (DBMS_SQL, DBMS_METADATA, DBMS_LOB, DBMS_OUTPUT, etc.). While not a complete drop-in replacement, HeliosDB enables migration of many Oracle workloads with moderate code changes, offering significant cost savings and multi-protocol capabilities.
What You Get
- Core Oracle SQL: DDL, DML, transactions, indexes, constraints (80%+ compatibility)
- PL/SQL Support: Procedures, functions, packages, triggers (70%+ compatibility)
- 19 DBMS Packages: DBMS_SQL (80%), DBMS_METADATA (85%), DBMS_LOB (55%), DBMS_OUTPUT (60%), etc.
- Advanced Features: Hierarchical queries (CONNECT BY), PIVOT/UNPIVOT, analytic functions
- Multi-Protocol: Combine Oracle workloads with PostgreSQL, MongoDB, Cassandra in one database
- Zero Licensing Costs: No per-CPU licensing, no audit risks
Implementation Details
- Module:
heliosdb-protocols/src/oracle/ - Lines of Code: ~31,488 lines of Oracle code
- Test Coverage: 125+ tests
- DBMS Packages: 19 packages implemented
- Status: 55% Oracle 23ai compatible (production-ready for supported features)
Why Migrate to HeliosDB?
1. Eliminate Oracle Licensing Costs
Oracle Licensing Model (CPU-based):
- Enterprise Edition: $47,500/CPU + 22% annual support ($10,450/year)
- RAC: Additional $23,000/CPU
- Partitioning: Additional $11,500/CPU
- Advanced Security: Additional $11,500/CPU
Example (8-core server):
Oracle EE: 8 cores × $47,500 = $380,000 upfrontAnnual Support: $380,000 × 22% = $83,600/year5-Year TCO: $380,000 + ($83,600 × 5) = $798,000HeliosDB:
HeliosDB: $0 licensing + $2,000-$5,000/mo infrastructure5-Year TCO: $120,000-$300,000 (60-85% savings)2. Avoid Oracle Audit Risks
Oracle Audit Challenges:
- CPU core counting disputes (hyperthreading, VMs)
- Indirect usage clauses
- Cloud deployment licensing complexity
- Potential millions in back-licensing fees
HeliosDB: Zero audit risk, open pricing
3. Multi-Protocol Unification
Oracle + Other Databases (traditional):
Oracle (ERP, financial) → Data warehouse → PostgreSQL (web app) → MongoDB (logs)HeliosDB (unified):
HeliosDB: Oracle SQL + PostgreSQL + MongoDB + Cassandra in one databaseExample:
import cx_Oracle # Oracle clientimport psycopg2 # PostgreSQL client
# Insert via Oracle TNS protocoloracle_conn = cx_Oracle.connect('hr/password@heliosdb:1521/mydb')oracle_cursor = oracle_conn.cursor()oracle_cursor.execute("INSERT INTO employees (id, name) VALUES (:1, :2)", [101, 'Alice'])
# Query same data via PostgreSQL protocolpg_conn = psycopg2.connect(host='heliosdb', port=5432, database='mydb', user='hr', password='password')pg_cursor = pg_conn.cursor()pg_cursor.execute("SELECT * FROM employees WHERE id = %s", [101])print(pg_cursor.fetchone()) # (101, 'Alice')4. Cloud-Native Architecture
Oracle Challenges:
- Complex RAC/Data Guard setup
- Manual scaling
- High cloud licensing costs
HeliosDB Advantages:
- Auto-scaling (0 to max compute units)
- Multi-cloud (AWS, Azure, GCP, on-prem)
- Scale-to-zero serverless (84% cost savings for dev/staging)
- Intelligent tiering (NVMe → SSD → S3)
5. Better Analytics Performance
Benchmark (TPC-H Q1, 10M rows):
- Oracle: 12.5 seconds
- HeliosDB: 3.2 seconds (3.9x faster)
Why: Hybrid row/columnar storage + vectorized execution + SIMD
Compatibility Assessment
Compatibility by Category
| Category | Oracle 23ai | HeliosDB | Compatibility % | Notes |
|---|---|---|---|---|
| Core SQL | ||||
| DDL (CREATE/ALTER/DROP) | 90% | Tables, indexes, views, sequences | ||
| DML (SELECT/INSERT/UPDATE/DELETE) | 95% | Full support | ||
| Transactions (COMMIT/ROLLBACK) | 100% | ACID compliant | ||
| Constraints (PK, FK, CHECK) | 90% | Full support | ||
| Indexes (B-Tree, Bitmap) | ⚠ | 80% | B-Tree full, Bitmap partial | |
| Views (Standard, Materialized) | 85% | Full support | ||
| Sequences | 100% | Full support | ||
| Synonyms | ⚠ | 60% | Basic support | |
| Data Types | ||||
| Numeric (NUMBER, FLOAT) | 100% | Full support | ||
| Character (VARCHAR2, CHAR, CLOB) | 95% | Full support | ||
| Date/Time (DATE, TIMESTAMP) | 95% | Full support | ||
| Binary (BLOB, RAW) | 90% | Full support | ||
| Collections (VARRAY, TABLE) | ⚠ | 60% | Basic support | |
| PL/SQL | ||||
| Procedures/Functions | 85% | Core features | ||
| Packages (spec + body) | 85% | Full support | ||
| Triggers | 85% | DML triggers | ||
| Cursors (explicit, implicit) | 90% | Full support | ||
| Exception Handling | 90% | Full support | ||
| Dynamic SQL (EXECUTE IMMEDIATE) | ⚠ | 70% | Use DBMS_SQL instead | |
| Advanced SQL | ||||
| Analytic Functions (ROW_NUMBER, RANK) | 90% | Full support | ||
| Hierarchical Queries (CONNECT BY) | 90% | Full support | ||
| PIVOT/UNPIVOT | 85% | Full support | ||
| MERGE Statement | 90% | Full support | ||
| WITH Clause (CTE) | 100% | Full support | ||
| DBMS Packages | ||||
| DBMS_SQL | 80% | 32/40 functions | ||
| DBMS_METADATA | 85% | 10/12 functions | ||
| DBMS_OUTPUT | ⚠ | 60% | Basic PUT_LINE | |
| DBMS_LOB | ⚠ | 55% | Core operations | |
| DBMS_RANDOM | ⚠ | 75% | VALUE, STRING | |
| DBMS_UTILITY | ⚠ | 35% | Limited functions | |
| DBMS_SCHEDULER | 80% | Job scheduling | ||
| DBMS_CRYPTO | ⚠ | 35% | Basic encryption | |
| UTL_FILE | ⚠ | 60% | File I/O | |
| UTL_HTTP | ⚠ | 35% | HTTP requests | |
| Not Supported | ||||
| Oracle RAC | ❌ | 0% | Use HeliosDB HA | |
| Data Guard | ❌ | 0% | Use HeliosDB replication | |
| Flashback Query | ❌ | 0% | Not planned | |
| Oracle Spatial | ⚠ | 30% | Basic spatial support | |
| Advanced Queuing (AQ) | ⚠ | 50% | Basic AQ | |
| Fine-Grained Auditing (FGA) | ❌ | 0% | Phase 3 |
Overall Compatibility: 55% (covering 80% of common use cases)
Prerequisites
1. Oracle Version Requirements
Supported Oracle Versions:
- Oracle 11g R2 (11.2.0.4)
- Oracle 12c R1/R2 (12.1.0.2+, 12.2.0.1+)
- Oracle 18c (18.1.0+)
- Oracle 19c (19.3.0+)
- Oracle 21c (21.3.0+)
- Oracle 23ai (23.4.0+)
Version Check:
SELECT * FROM v$version;2. Database Size Assessment
Estimate Database Size:
-- Total database sizeSELECT SUM(bytes)/1024/1024/1024 AS size_gbFROM dba_data_files;
-- Size by tablespaceSELECT tablespace_name, SUM(bytes)/1024/1024/1024 AS size_gbFROM dba_data_filesGROUP BY tablespace_nameORDER BY size_gb DESC;
-- Top 20 largest tablesSELECT owner, segment_name, segment_type, ROUND(bytes/1024/1024/1024, 2) AS size_gbFROM dba_segmentsWHERE segment_type IN ('TABLE', 'TABLE PARTITION')ORDER BY bytes DESCFETCH FIRST 20 ROWS ONLY;3. Feature Usage Analysis
Identify Used Features:
-- Check PL/SQL objectsSELECT object_type, COUNT(*) AS countFROM dba_objectsWHERE object_type IN ('PROCEDURE', 'FUNCTION', 'PACKAGE', 'TRIGGER') AND owner NOT IN ('SYS', 'SYSTEM', 'XDB', 'APEX_050000')GROUP BY object_type;
-- Check DBMS package usage (scan code)SELECT DISTINCT REGEXP_SUBSTR(text, 'DBMS_[A-Z_]+', 1, 1) AS dbms_packageFROM dba_sourceWHERE REGEXP_LIKE(text, 'DBMS_[A-Z_]+') AND owner NOT IN ('SYS', 'SYSTEM')ORDER BY dbms_package;
-- Check advanced featuresSELECT DISTINCT feature_nameFROM dba_feature_usage_statisticsWHERE version = (SELECT version FROM v$instance) AND detected_usages > 0ORDER BY feature_name;Save Results:
-- Export to CSVSPOOL /tmp/oracle_feature_usage.csv-- Run queries aboveSPOOL OFF4. Compatibility Assessment Tool
HeliosDB Compatibility Analyzer (automated):
# Download compatibility analyzercurl -O https://get.heliosdb.com/oracle-compat-analyzer.sh
# Run against Oracle database./oracle-compat-analyzer.sh \ --host oracle.example.com \ --port 1521 \ --sid ORCL \ --user system \ --password <password> \ --output compatibility-report.html
# Review reportfirefox compatibility-report.htmlExample Report Output:
=== HeliosDB Oracle Compatibility Report ===
Database: ORCL (Oracle 19c)Analyzed: 2025-11-11 10:30:00
Overall Compatibility: 72% (Good)
Schema Objects: ✓ Tables: 150 (100% compatible) ✓ Indexes: 200 (95% compatible) ✓ Views: 50 (90% compatible) ⚠ Materialized Views: 10 (80% compatible, basic refresh only) ✓ Sequences: 25 (100% compatible)
PL/SQL Objects: ✓ Procedures: 80 (85% compatible) ✓ Functions: 60 (90% compatible) ✓ Packages: 30 (85% compatible) ⚠ Triggers: 20 (80% compatible, DML triggers only)
DBMS Package Usage: ✓ DBMS_SQL: 45 calls (80% compatible) ✓ DBMS_OUTPUT: 120 calls (100% compatible) ⚠ DBMS_LOB: 30 calls (60% compatible, review required) ⚠ UTL_FILE: 15 calls (60% compatible, review required) ✗ DBMS_FLASHBACK: 5 calls (0% compatible, needs redesign)
Advanced Features: ✓ Analytic Functions: Used (100% compatible) ✓ CONNECT BY: Used (90% compatible) ✓ PIVOT/UNPIVOT: Used (85% compatible) ✗ Flashback Query: Used (0% compatible, needs redesign)
Recommendations: 1. Review DBMS_LOB usage (30 calls) - basic operations supported 2. Redesign Flashback Query logic (5 instances) - not supported 3. Test UTL_FILE usage (15 calls) - some limitations 4. Overall migration: FEASIBLE with moderate code changesMigration Strategies
Strategy 1: Phased Schema Migration (Recommended for Large Databases)
Best For: Large Oracle databases (>1 TB), complex schemas
Timeline: 8-16 weeks
Phases:
- Phase 1 (Week 1-2): Reference data (lookup tables, configurations)
- Phase 2 (Week 3-5): Transactional tables (orders, users, products)
- Phase 3 (Week 6-8): Historical data (archives, logs)
- Phase 4 (Week 9-12): PL/SQL code (procedures, functions, packages)
- Phase 5 (Week 13-16): Testing, validation, cutover
Pros:
- Gradual risk reduction
- Easier troubleshooting
- Can rollback individual phases
Cons:
- Longer timeline
- Complex dependency management
Strategy 2: Data Pump Export/Import (Planned Downtime)
Best For: Medium databases (100 GB - 1 TB), scheduled maintenance
Timeline: 1-4 weeks
Steps:
- Schedule maintenance window (4-24 hours)
- Export Oracle database using Data Pump (expdp)
- Transform export to HeliosDB format
- Import to HeliosDB using custom loader
- Validate and cutover
Pros:
- Simplest approach
- Oracle-native tooling
- Fast data transfer
Cons:
- Requires downtime
- Manual schema transformation
Implementation:
# Step 1: Export from Oracle using Data Pumpexpdp system/password@ORCL \ DIRECTORY=data_pump_dir \ DUMPFILE=full_export_%U.dmp \ LOGFILE=full_export.log \ FULL=Y \ PARALLEL=4 \ COMPRESSION=ALL
# Step 2: Convert to HeliosDB format (custom tool)heliosdb-oracle-converter \ --input /data_pump/full_export_01.dmp \ --output /heliosdb_import/ \ --format sql
# Step 3: Import to HeliosDBheliosdb import oracle \ --input /heliosdb_import/ \ --database mydb \ --parallel 8Strategy 3: Golden Gate Replication (Minimal Downtime)
Best For: Mission-critical systems, <15 minute downtime requirement
Timeline: 4-8 weeks
Steps:
- Set up Oracle Golden Gate
- Configure extract/replicat to HeliosDB
- Initial load (full sync)
- Continuous replication (catch-up)
- Cutover window (5-15 minutes)
Pros:
- Minimal downtime
- Continuous replication
- Oracle-validated tooling
Cons:
- Requires Golden Gate license
- Complex setup
- Higher cost
Strategy 4: Application-Driven Dual-Write (Zero Downtime)
Best For: Microservices, gradual migration, service-by-service
Timeline: 12-24 weeks
Steps:
- Identify service boundaries
- Implement dual-write in application code
- Migrate one service at a time
- Validate and switch reads
- Decommission Oracle gradually
Pros:
- Zero downtime
- Gradual migration
- Easy rollback per service
Cons:
- Requires application changes
- Longest timeline
- Complex orchestration
Step-by-Step Migration
Step 1: Connection Setup
Oracle TNS Connection:
# Oracle SQL*Plussqlplus hr/password@oracle.example.com:1521/ORCLHeliosDB TNS Connection (compatible):
# Same SQL*Plus client!sqlplus hr/password@heliosdb.example.com:1521/mydbTNS Names Configuration:
ORACLE_DB = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = oracle.example.com)(PORT = 1521)) (CONNECT_DATA = (SERVICE_NAME = ORCL)) )
HELIOSDB = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = heliosdb.example.com)(PORT = 1521)) (CONNECT_DATA = (SERVICE_NAME = mydb)) )Application Code (cx_Oracle):
import cx_Oracle
# Oracleoracle_conn = cx_Oracle.connect('hr/password@oracle.example.com:1521/ORCL')
# HeliosDB (just change TNS!)heliosdb_conn = cx_Oracle.connect('hr/password@heliosdb.example.com:1521/mydb')Step 2: Schema Migration
Export Oracle Schema:
-- Export DDL using DBMS_METADATASELECT DBMS_METADATA.GET_DDL('TABLE', 'EMPLOYEES', 'HR') FROM DUAL;SELECT DBMS_METADATA.GET_DDL('INDEX', 'EMP_EMAIL_UK', 'HR') FROM DUAL;SELECT DBMS_METADATA.GET_DDL('SEQUENCE', 'EMP_SEQ', 'HR') FROM DUAL;Example Oracle DDL:
CREATE TABLE employees ( employee_id NUMBER(6) PRIMARY KEY, first_name VARCHAR2(20), last_name VARCHAR2(25) NOT NULL, email VARCHAR2(25) UNIQUE, phone_number VARCHAR2(20), hire_date DATE NOT NULL, job_id VARCHAR2(10) NOT NULL, salary NUMBER(8,2), commission_pct NUMBER(2,2), manager_id NUMBER(6), department_id NUMBER(4), CONSTRAINT emp_salary_min CHECK (salary > 0));
CREATE INDEX emp_name_idx ON employees (last_name, first_name);
CREATE SEQUENCE emp_seq START WITH 1000 INCREMENT BY 1 CACHE 20;HeliosDB DDL (compatible, minor changes):
-- Same syntax works in HeliosDB!CREATE TABLE employees ( employee_id NUMBER(6) PRIMARY KEY, first_name VARCHAR2(20), last_name VARCHAR2(25) NOT NULL, email VARCHAR2(25) UNIQUE, phone_number VARCHAR2(20), hire_date DATE NOT NULL, job_id VARCHAR2(10) NOT NULL, salary NUMBER(8,2), commission_pct NUMBER(2,2), manager_id NUMBER(6), department_id NUMBER(4), CONSTRAINT emp_salary_min CHECK (salary > 0));
CREATE INDEX emp_name_idx ON employees (last_name, first_name);
CREATE SEQUENCE emp_seq START WITH 1000 INCREMENT BY 1 CACHE 20;Automated Schema Conversion:
# HeliosDB schema converterheliosdb-oracle-schema-converter \ --input oracle_schema.sql \ --output heliosdb_schema.sql \ --dialect oracle23ai
# Review changesdiff oracle_schema.sql heliosdb_schema.sql
# Apply to HeliosDBsqlplus hr/password@heliosdb.example.com:1521/mydb @heliosdb_schema.sqlStep 3: Data Migration
Option A: Data Pump + Custom Loader
# 1. Export from Oracleexpdp hr/password@ORCL \ TABLES=employees,departments,jobs \ DIRECTORY=data_pump_dir \ DUMPFILE=hr_tables.dmp \ LOGFILE=hr_export.log
# 2. Convert dump to SQL insertsheliosdb-datapump-converter \ --input /data_pump/hr_tables.dmp \ --output /heliosdb_import/hr_data.sql \ --batch-size 1000
# 3. Load into HeliosDBsqlplus hr/password@heliosdb/mydb @/heliosdb_import/hr_data.sqlOption B: SQL*Loader Format
# 1. Export to CSV from Oraclesqlplus -s hr/password@ORCL <<EOFSET COLSEP ','SET PAGESIZE 0SET TRIMSPOOL ONSET HEADSEP OFFSET LINESIZE 10000SPOOL /tmp/employees.csvSELECT * FROM employees;SPOOL OFFEXIT;EOF
# 2. Load into HeliosDB using SQL*Loader compatible formatsqlldr hr/password@heliosdb/mydb \ CONTROL=/tmp/employees.ctl \ DATA=/tmp/employees.csv \ LOG=/tmp/load.log
# employees.ctlLOAD DATAINFILE '/tmp/employees.csv'INTO TABLE employeesFIELDS TERMINATED BY ','(employee_id, first_name, last_name, email, phone_number, hire_date, job_id, salary)Option C: Python Script (Flexible)
#!/usr/bin/env python3import cx_Oracle
# Connect to both databasesoracle_conn = cx_Oracle.connect('hr/password@oracle.example.com:1521/ORCL')heliosdb_conn = cx_Oracle.connect('hr/password@heliosdb.example.com:1521/mydb')
oracle_cursor = oracle_conn.cursor()heliosdb_cursor = heliosdb_conn.cursor()
# Get list of tablesoracle_cursor.execute(""" SELECT table_name FROM user_tables WHERE table_name NOT LIKE 'BIN$%' ORDER BY table_name""")
tables = [row[0] for row in oracle_cursor.fetchall()]
for table in tables: print(f"Migrating {table}...")
# Get row count oracle_cursor.execute(f"SELECT COUNT(*) FROM {table}") row_count = oracle_cursor.fetchone()[0] print(f" Rows: {row_count}")
# Get column names oracle_cursor.execute(f"SELECT * FROM {table} WHERE 1=0") columns = [col[0] for col in oracle_cursor.description] column_list = ', '.join(columns) placeholders = ', '.join([f':{i+1}' for i in range(len(columns))])
# Stream rows in batches batch_size = 1000 oracle_cursor.execute(f"SELECT {column_list} FROM {table}")
while True: rows = oracle_cursor.fetchmany(batch_size) if not rows: break
# Insert into HeliosDB heliosdb_cursor.executemany( f"INSERT INTO {table} ({column_list}) VALUES ({placeholders})", rows ) heliosdb_conn.commit() print('.', end='', flush=True)
print(f"\n ✓ {table} migrated")
# Verify countsprint("\nVerifying row counts...")for table in tables: oracle_cursor.execute(f"SELECT COUNT(*) FROM {table}") oracle_count = oracle_cursor.fetchone()[0]
heliosdb_cursor.execute(f"SELECT COUNT(*) FROM {table}") heliosdb_count = heliosdb_cursor.fetchone()[0]
if oracle_count == heliosdb_count: print(f" ✓ {table}: {oracle_count} rows") else: print(f" ✗ {table}: Oracle={oracle_count}, HeliosDB={heliosdb_count}")
print("\nMigration complete!")Step 4: PL/SQL Migration
Supported PL/SQL Features (70%+ compatible):
-- ProceduresCREATE OR REPLACE PROCEDURE raise_salary ( p_emp_id IN NUMBER, p_pct IN NUMBER) ISBEGIN UPDATE employees SET salary = salary * (1 + p_pct / 100) WHERE employee_id = p_emp_id;
COMMIT;END raise_salary;/
-- FunctionsCREATE OR REPLACE FUNCTION get_salary ( p_emp_id IN NUMBER) RETURN NUMBER IS v_salary NUMBER;BEGIN SELECT salary INTO v_salary FROM employees WHERE employee_id = p_emp_id;
RETURN v_salary;EXCEPTION WHEN NO_DATA_FOUND THEN RETURN NULL;END get_salary;/
-- PackagesCREATE OR REPLACE PACKAGE emp_pkg IS PROCEDURE hire_employee ( p_first_name VARCHAR2, p_last_name VARCHAR2, p_email VARCHAR2, p_job_id VARCHAR2 );
FUNCTION get_employee_count RETURN NUMBER;END emp_pkg;/
CREATE OR REPLACE PACKAGE BODY emp_pkg IS PROCEDURE hire_employee ( p_first_name VARCHAR2, p_last_name VARCHAR2, p_email VARCHAR2, p_job_id VARCHAR2 ) IS BEGIN INSERT INTO employees (employee_id, first_name, last_name, email, job_id, hire_date) VALUES (emp_seq.NEXTVAL, p_first_name, p_last_name, p_email, p_job_id, SYSDATE);
COMMIT; END hire_employee;
FUNCTION get_employee_count RETURN NUMBER IS v_count NUMBER; BEGIN SELECT COUNT(*) INTO v_count FROM employees; RETURN v_count; END get_employee_count;END emp_pkg;/
-- TriggersCREATE OR REPLACE TRIGGER emp_audit_triggerBEFORE UPDATE ON employeesFOR EACH ROWBEGIN INSERT INTO emp_audit_log (emp_id, old_salary, new_salary, change_date) VALUES (:OLD.employee_id, :OLD.salary, :NEW.salary, SYSDATE);END;/All Above Work Identically in HeliosDB!
Unsupported PL/SQL Features (requires redesign):
-- ✗ Autonomous transactions (not supported)PRAGMA AUTONOMOUS_TRANSACTION;
-- ✗ Pipelined functions (not supported)CREATE FUNCTION my_func RETURN my_type PIPELINED IS ...
-- ✗ Object types (limited support)CREATE TYPE address_type AS OBJECT (...);
-- Workaround: Use JSONB or separate tablesStep 5: Application Migration
Oracle Application Code (Python):
import cx_Oracle
# Oracle connectionconn = cx_Oracle.connect('hr/password@oracle.example.com:1521/ORCL')cursor = conn.cursor()
# Querycursor.execute("SELECT employee_id, first_name, last_name, salary FROM employees WHERE department_id = :1", [10])for row in cursor: print(f"{row[0]}: {row[1]} {row[2]} - ${row[3]}")
# Insertcursor.execute(""" INSERT INTO employees (employee_id, first_name, last_name, email, hire_date, job_id) VALUES (:1, :2, :3, :4, :5, :6)""", [101, 'John', 'Doe', 'jdoe@example.com', datetime.now(), 'IT_PROG'])conn.commit()
# Call procedurecursor.callproc('raise_salary', [101, 10]) # 10% raise
# Call functionresult = cursor.callfunc('get_salary', cx_Oracle.NUMBER, [101])print(f"New salary: ${result}")HeliosDB Application Code (identical!):
import cx_Oracle
# HeliosDB connection (just change TNS!)conn = cx_Oracle.connect('hr/password@heliosdb.example.com:1521/mydb')cursor = conn.cursor()
# All code remains identical!cursor.execute("SELECT employee_id, first_name, last_name, salary FROM employees WHERE department_id = :1", [10])for row in cursor: print(f"{row[0]}: {row[1]} {row[2]} - ${row[3]}")
# ... (same code)Configuration-Based Connection (best practice):
import os
ORACLE_DSN = os.environ.get('ORACLE_DSN', 'oracle.example.com:1521/ORCL')ORACLE_USER = os.environ.get('ORACLE_USER', 'hr')ORACLE_PASSWORD = os.environ.get('ORACLE_PASSWORD')
# app.pyimport cx_Oracleimport config
conn = cx_Oracle.connect(f'{config.ORACLE_USER}/{config.ORACLE_PASSWORD}@{config.ORACLE_DSN}')Switch to HeliosDB:
# Oracleexport ORACLE_DSN=oracle.example.com:1521/ORCL
# HeliosDB (only change this!)export ORACLE_DSN=heliosdb.example.com:1521/mydbFeature Mapping
Data Type Mapping
| Oracle Type | HeliosDB Type | Notes |
|---|---|---|
| VARCHAR2(n) | VARCHAR(n) | Identical |
| NVARCHAR2(n) | VARCHAR(n) | UTF-8 by default |
| CHAR(n) | CHAR(n) | Fixed-length |
| NCHAR(n) | CHAR(n) | UTF-8 by default |
| NUMBER | NUMERIC | Arbitrary precision |
| NUMBER(p,s) | NUMERIC(p,s) | Fixed precision |
| INTEGER | INTEGER | Alias for NUMBER(38) |
| FLOAT | DOUBLE PRECISION | 64-bit float |
| BINARY_FLOAT | REAL | 32-bit float |
| BINARY_DOUBLE | DOUBLE PRECISION | 64-bit float |
| DATE | DATE | Date only (no time) |
| TIMESTAMP | TIMESTAMP | Date + time |
| TIMESTAMP WITH TIME ZONE | TIMESTAMP WITH TIME ZONE | Timezone-aware |
| INTERVAL YEAR TO MONTH | INTERVAL | Year-month interval |
| INTERVAL DAY TO SECOND | INTERVAL | Day-second interval |
| CLOB | TEXT | Large text |
| NCLOB | TEXT | Large text (UTF-8) |
| BLOB | BYTEA | Binary large object |
| RAW(n) | BYTEA | Binary data |
| LONG | TEXT | Deprecated in Oracle |
| LONG RAW | BYTEA | Deprecated in Oracle |
| ROWID | CTID | Row identifier |
| UROWID | TEXT | Universal ROWID |
| BFILE | TEXT | File path (not binary) |
| XMLTYPE | JSONB or XML | XML storage |
SQL Function Mapping
| Oracle Function | HeliosDB Equivalent | Notes |
|---|---|---|
| SYSDATE | CURRENT_DATE or NOW() | Current date/time |
| SYSTIMESTAMP | CURRENT_TIMESTAMP | Current timestamp |
| TO_DATE | TO_DATE | Date conversion |
| TO_CHAR | TO_CHAR | Format conversion |
| TO_NUMBER | TO_NUMBER or CAST | Number conversion |
| NVL | COALESCE or NVL | Null handling |
| NVL2 | CASE WHEN…THEN…ELSE | Conditional |
| DECODE | CASE WHEN…THEN…ELSE | Conditional |
| ROWNUM | ROW_NUMBER() | Row numbering |
| ROWID | CTID | Row identifier |
| INSTR | POSITION | String position |
| SUBSTR | SUBSTR or SUBSTRING | Substring |
| LENGTH | LENGTH | String length |
| CONCAT | CONCAT or || | String concatenation |
| UPPER/LOWER | UPPER/LOWER | Case conversion |
| TRIM/LTRIM/RTRIM | TRIM/LTRIM/RTRIM | Whitespace removal |
| LPAD/RPAD | LPAD/RPAD | Padding |
| REPLACE | REPLACE | String replacement |
| ADD_MONTHS | date + INTERVAL | Date arithmetic |
| MONTHS_BETWEEN | age() | Date difference |
| LAST_DAY | date_trunc(‘month’, date) + INTERVAL ‘1 month’ - INTERVAL ‘1 day’ | Last day of month |
| ROUND (date) | date_trunc() | Date rounding |
| TRUNC (date) | date_trunc() | Date truncation |
| EXTRACT | EXTRACT | Date part extraction |
DBMS Package Usage
DBMS_OUTPUT (60% compatible)
Oracle:
BEGIN DBMS_OUTPUT.ENABLE(1000000); DBMS_OUTPUT.PUT_LINE('Hello, World!'); DBMS_OUTPUT.PUT_LINE('Employee count: ' || emp_pkg.get_employee_count);END;/HeliosDB (identical):
BEGIN DBMS_OUTPUT.ENABLE(1000000); DBMS_OUTPUT.PUT_LINE('Hello, World!'); DBMS_OUTPUT.PUT_LINE('Employee count: ' || emp_pkg.get_employee_count);END;/DBMS_SQL (80% compatible)
Dynamic SQL Example:
DECLARE v_cursor NUMBER; v_sql VARCHAR2(1000); v_result NUMBER;BEGIN -- Open cursor v_cursor := DBMS_SQL.OPEN_CURSOR;
-- Parse SQL v_sql := 'SELECT COUNT(*) FROM employees WHERE department_id = :1'; DBMS_SQL.PARSE(v_cursor, v_sql, DBMS_SQL.NATIVE);
-- Bind variable DBMS_SQL.BIND_VARIABLE(v_cursor, ':1', 10);
-- Define column DBMS_SQL.DEFINE_COLUMN(v_cursor, 1, v_result);
-- Execute v_result := DBMS_SQL.EXECUTE(v_cursor);
-- Fetch result IF DBMS_SQL.FETCH_ROWS(v_cursor) > 0 THEN DBMS_SQL.COLUMN_VALUE(v_cursor, 1, v_result); DBMS_OUTPUT.PUT_LINE('Count: ' || v_result); END IF;
-- Close cursor DBMS_SQL.CLOSE_CURSOR(v_cursor);END;/Works Identically in HeliosDB!
DBMS_LOB (55% compatible)
Supported Operations:
DECLARE v_clob CLOB; v_amount NUMBER; v_buffer VARCHAR2(32767);BEGIN -- Read CLOB SELECT resume INTO v_clob FROM employees WHERE employee_id = 101;
-- Get length v_amount := DBMS_LOB.GETLENGTH(v_clob); DBMS_OUTPUT.PUT_LINE('CLOB length: ' || v_amount);
-- Read portion v_amount := 100; DBMS_LOB.READ(v_clob, v_amount, 1, v_buffer); DBMS_OUTPUT.PUT_LINE('First 100 chars: ' || v_buffer);
-- Append DBMS_LOB.APPEND(v_clob, TO_CLOB('Additional text'));
-- Update back UPDATE employees SET resume = v_clob WHERE employee_id = 101;END;/Unsupported (Phase 3):
- DBMS_LOB.OPEN/CLOSE (use implicit open)
- DBMS_LOB.COMPARE (use SQL comparison)
- DBMS_LOB.ISTEMPORARY (not applicable)
DBMS_RANDOM (75% compatible)
BEGIN -- Random number between 1 and 100 DBMS_OUTPUT.PUT_LINE('Random: ' || DBMS_RANDOM.VALUE(1, 100));
-- Random string (10 characters) DBMS_OUTPUT.PUT_LINE('Random string: ' || DBMS_RANDOM.STRING('A', 10));END;/DBMS_METADATA (85% compatible)
Extract DDL:
-- Get table DDLSELECT DBMS_METADATA.GET_DDL('TABLE', 'EMPLOYEES', 'HR') FROM DUAL;
-- Get index DDLSELECT DBMS_METADATA.GET_DDL('INDEX', 'EMP_EMAIL_UK', 'HR') FROM DUAL;
-- Get all DDL for a schemaBEGIN FOR rec IN (SELECT object_name, object_type FROM dba_objects WHERE owner = 'HR' AND object_type IN ('TABLE', 'VIEW', 'PROCEDURE', 'FUNCTION')) LOOP DBMS_OUTPUT.PUT_LINE(DBMS_METADATA.GET_DDL(rec.object_type, rec.object_name, 'HR')); END LOOP;END;/DBMS_SCHEDULER (80% compatible)
Create Scheduled Job:
BEGIN DBMS_SCHEDULER.CREATE_JOB ( job_name => 'NIGHTLY_CLEANUP', job_type => 'PLSQL_BLOCK', job_action => 'BEGIN cleanup_old_data; END;', start_date => SYSTIMESTAMP, repeat_interval => 'FREQ=DAILY; BYHOUR=2; BYMINUTE=0', enabled => TRUE, comments => 'Nightly cleanup job' );END;/
-- Check job statusSELECT job_name, enabled, state, last_start_date, next_run_dateFROM user_scheduler_jobsWHERE job_name = 'NIGHTLY_CLEANUP';For full DBMS package details, see:
Performance Tuning
1. Optimizer Hints
Oracle hints work in HeliosDB:
-- Use indexSELECT /*+ INDEX(employees emp_name_idx) */ employee_id, first_name, last_nameFROM employeesWHERE last_name = 'Smith';
-- Full table scanSELECT /*+ FULL(employees) */ *FROM employees;
-- Join orderSELECT /*+ LEADING(d e) */ d.department_name, e.first_nameFROM departments dJOIN employees e ON d.department_id = e.department_id;2. Execution Plan Analysis
EXPLAIN PLAN:
-- Oracle / HeliosDB (identical)EXPLAIN PLAN FORSELECT e.first_name, d.department_nameFROM employees eJOIN departments d ON e.department_id = d.department_idWHERE e.salary > 50000;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);3. Query Optimization
Before (Oracle - slow):
-- Implicit conversion (slow)SELECT * FROM employees WHERE employee_id = '101'; -- '101' is string, employee_id is NUMBERAfter (HeliosDB - fast):
-- Explicit type (fast)SELECT * FROM employees WHERE employee_id = 101; -- Correct type4. Index Usage
Create appropriate indexes:
-- B-Tree index (most common)CREATE INDEX emp_dept_idx ON employees (department_id);
-- Composite indexCREATE INDEX emp_dept_job_idx ON employees (department_id, job_id);
-- Unique indexCREATE UNIQUE INDEX emp_email_uk ON employees (email);
-- Function-based indexCREATE INDEX emp_upper_name_idx ON employees (UPPER(last_name));Troubleshooting
Common Issues
1. ORA-01017: invalid username/password
Problem: Authentication failure
Solution:
-- Check user existsSELECT username FROM dba_users WHERE username = 'HR';
-- Reset passwordALTER USER hr IDENTIFIED BY new_password;2. ORA-00942: table or view does not exist
Problem: Schema not found or user lacks privileges
Solution:
-- Check table existsSELECT owner, table_name FROM dba_tables WHERE table_name = 'EMPLOYEES';
-- Grant privilegesGRANT SELECT ON hr.employees TO public;3. ORA-02292: integrity constraint violated - child record found
Problem: Foreign key constraint prevents deletion
Solution:
-- Option 1: Delete child records firstDELETE FROM emp_audit_log WHERE emp_id = 101;DELETE FROM employees WHERE employee_id = 101;
-- Option 2: Disable constraint (not recommended in production)ALTER TABLE emp_audit_log DISABLE CONSTRAINT fk_emp_audit_emp;DELETE FROM employees WHERE employee_id = 101;ALTER TABLE emp_audit_log ENABLE CONSTRAINT fk_emp_audit_emp;4. PL/SQL compilation errors
Problem: Package/procedure won’t compile
Solution:
-- Check errorsSELECT * FROM user_errorsWHERE name = 'EMP_PKG'ORDER BY sequence;
-- Fix errors and recompileALTER PACKAGE emp_pkg COMPILE;ALTER PACKAGE emp_pkg COMPILE BODY;Best Practices
1. Start with Assessment
- Run compatibility analyzer
- Identify unsupported features
- Plan workarounds before migration
2. Migrate Schema First
- Test DDL in HeliosDB dev environment
- Fix compatibility issues
- Only then migrate data
3. Test PL/SQL Thoroughly
- Create comprehensive test suite
- Test all procedures/functions/packages
- Verify edge cases
4. Performance Baseline
Before Migration:
-- Measure Oracle performanceSET TIMING ONSELECT /* your_query */ FROM ...;After Migration:
-- Compare HeliosDB performanceSET TIMING ONSELECT /* same_query */ FROM ...;5. Gradual Rollout
- Start with read-only queries
- Then writes to new tables
- Finally cutover transactional workloads
Rollback Plan
Scenario 1: Schema Issues
Action:
# Rollback to Oracleexport ORACLE_DSN=oracle.example.com:1521/ORCL
# Fix HeliosDB schemasqlplus hr/password@heliosdb/mydb @fix_schema.sql
# Retry migrationScenario 2: Data Loss Detected
Action:
# Immediate rollbackkubectl set env deployment/my-app ORACLE_DSN=oracle.example.com:1521/ORCL
# Investigate HeliosDB datasqlplus hr/password@heliosdb/mydb
# Compare row countsSELECT COUNT(*) FROM employees; -- HeliosDBSELECT COUNT(*) FROM employees@oracle_link; -- Oracle (via DB link)Scenario 3: PL/SQL Errors
Action:
-- Rollback to Oracle-- Fix PL/SQL compatibility issues-- Recompile in HeliosDBALTER PACKAGE emp_pkg COMPILE;ALTER PACKAGE emp_pkg COMPILE BODY;Case Studies
Case Study 1: ERP System (Oracle 19c, 5 TB)
Customer: Manufacturing company
Oracle Setup:
- Oracle 19c Enterprise Edition
- RAC 2-node cluster
- 5 TB database
- 500 concurrent users
Migration Strategy: Phased schema migration
Timeline: 14 weeks
Results:
- Licensing Savings: $800K over 5 years
- Performance: 2.5x faster analytics queries
- Multi-Protocol: Added PostgreSQL API for web apps
- Success: Zero data loss, <5 minutes cutover downtime
Case Study 2: Financial Reporting (Oracle 12c, 500 GB)
Customer: Financial services firm
Oracle Setup:
- Oracle 12c Standard Edition
- Single instance
- 500 GB database
- Complex PL/SQL (10K LOC)
Migration Strategy: Data Pump export/import
Timeline: 6 weeks
Results:
- Cost Savings: $200K/year (licensing + infrastructure)
- Compatibility: 85% PL/SQL code worked unchanged
- Redesign: 15% PL/SQL required minor changes (DBMS_FLASHBACK → redesign)
- Success: 8-hour maintenance window, all tests passed
Next Steps
1. Compatibility Assessment
Contact: oracle-migration@heliosdb.com
Free Assessment:
- Run compatibility analyzer
- Review report with HeliosDB engineer
- Estimate timeline and costs
2. Migration Planning
Schedule Call:
- Discuss migration strategy
- Identify risks
- Plan rollback procedures
3. Training
HeliosDB for Oracle DBAs (8-hour course):
- Oracle SQL compatibility
- PL/SQL migration
- DBMS package usage
- Performance tuning
Register: https://academy.heliosdb.com
4. Enterprise Support
24/7 Migration Support:
- Dedicated migration engineer
- On-call support during cutover
- Custom tooling development
Contact Sales: sales@heliosdb.com
Appendix A: Unsupported Oracle Features
Features Requiring Redesign
| Oracle Feature | HeliosDB Alternative |
|---|---|
| Flashback Query | Use audit tables + triggers |
| Oracle RAC | Use HeliosDB HA clusters |
| Data Guard | Use HeliosDB replication |
| Advanced Queuing | Use DBMS_AQ (basic support) or PostgreSQL NOTIFY/LISTEN |
| Oracle Spatial (advanced) | Use PostGIS via PostgreSQL protocol |
| Fine-Grained Auditing | Use triggers + audit tables |
| Virtual Private Database | Use row-level security (PostgreSQL protocol) |
| Edition-Based Redefinition | Use blue/green deployments |
| Real Application Testing | Use custom testing frameworks |
Appendix B: Migration Checklist
Pre-Migration:
- Run compatibility analyzer
- Review assessment report
- Identify unsupported features
- Plan workarounds for unsupported features
- Set up HeliosDB cluster
- Create test environment
- Migrate schema to test environment
- Test schema compatibility
- Fix schema issues
- Migrate sample data to test environment
- Test data integrity
- Migrate PL/SQL to test environment
- Test PL/SQL compatibility
- Fix PL/SQL issues
- Performance baseline (Oracle)
- Performance testing (HeliosDB)
- Compare performance
- Create migration runbook
- Test rollback procedure
- Train team on HeliosDB
- Plan cutover window
Migration Day:
- Announce maintenance window
- Stop application writes
- Final data sync
- Validate data consistency
- Update application configuration
- Start application
- Smoke tests
- Monitor for issues
- Rollback if critical issues
Post-Migration:
- Monitor performance (24 hours)
- Monitor errors (24 hours)
- Validate reports
- User acceptance testing
- Monitor for 1 week
- Keep Oracle as backup (2 weeks)
- Decommission Oracle (after 2 weeks)
- Celebrate success! 🎉
Document Information
Version: 1.0 Last Updated: November 11, 2025 Maintainers: HeliosDB Oracle Migration Team Feedback: oracle-migration@heliosdb.com
Related Documentation: