SQL Migration Tips
SQL Migration Tips
Last Updated: January 4, 2026
This guide provides tips and best practices for migrating SQL workloads from other database systems to HeliosDB.
Table of Contents
- General Migration Strategy
- Migration from PostgreSQL
- Migration from MySQL
- Migration from Oracle
- Migration from SQL Server
- Migration from MongoDB
- Schema Migration
- Data Migration
- Query Migration
- Testing and Validation
General Migration Strategy
Phase 1: Assessment
-
Inventory existing schema
- List all tables, views, indexes
- Document data types and constraints
- Identify stored procedures and functions
-
Analyze query patterns
- Extract frequent queries
- Identify performance-critical queries
- Document transaction patterns
-
Estimate data volume
- Current data size
- Growth rate
- Retention requirements
Phase 2: Schema Conversion
- Map data types (see source-specific sections)
- Convert constraints and indexes
- Handle source-specific features
Phase 3: Data Migration
- Initial bulk load
- Verify data integrity
- Set up CDC for ongoing sync (if dual-running)
Phase 4: Application Migration
- Update connection strings
- Convert incompatible queries
- Test and validate
Migration from PostgreSQL
Compatibility
HeliosDB uses the PostgreSQL wire protocol, making migration straightforward.
High Compatibility:
- Data types
- SQL syntax
- Client libraries
- Connection strings
Data Type Mapping
| PostgreSQL | HeliosDB | Notes |
|---|---|---|
serial | BIGINT + sequence | Use identity columns |
bigserial | BIGINT + sequence | Use identity columns |
money | NUMERIC | Convert to numeric |
cidr/inet | VARCHAR | Store as text |
macaddr | VARCHAR | Store as text |
point/line/box | JSONB | Store as JSON |
| All others | Same | Direct compatibility |
Connection String
# PostgreSQLpostgresql://user:pass@host:5432/dbname
# HeliosDB (same format)postgresql://user:pass@host:5432/dbnameKnown Differences
1. Extensions: Some PostgreSQL extensions may not be available
-- PostgreSQL (may not work)CREATE EXTENSION postgis;
-- HeliosDB: Use built-in geospatial typesCREATE TABLE locations ( id BIGINT PRIMARY KEY, point GEOSPATIAL);2. System catalogs: Some pg_catalog views differ
-- May need adjustment for introspection queriesSELECT * FROM pg_stat_activity; -- Limited supportMigration from MySQL
Data Type Mapping
| MySQL | HeliosDB | Notes |
|---|---|---|
TINYINT | SMALLINT | Wider range |
INT UNSIGNED | BIGINT | Use signed |
FLOAT | REAL | IEEE 754 |
DOUBLE | DOUBLE PRECISION | Standard name |
DATETIME | TIMESTAMP | With timezone |
ENUM | VARCHAR + CHECK | Use constraint |
SET | TEXT[] | Array type |
BLOB | BYTEA | Binary data |
TEXT | TEXT | Same |
JSON | JSONB | Binary JSON |
SQL Syntax Differences
1. String concatenation
-- MySQLSELECT CONCAT(first_name, ' ', last_name) FROM users;
-- HeliosDB (same, or use ||)SELECT first_name || ' ' || last_name FROM users;2. LIMIT with OFFSET
-- MySQLSELECT * FROM users LIMIT 10, 20; -- offset 10, limit 20
-- HeliosDBSELECT * FROM users LIMIT 20 OFFSET 10;3. Date functions
-- MySQLSELECT DATE_ADD(NOW(), INTERVAL 1 DAY);
-- HeliosDBSELECT NOW() + INTERVAL '1 day';4. AUTO_INCREMENT
-- MySQLCREATE TABLE t (id INT AUTO_INCREMENT PRIMARY KEY);
-- HeliosDBCREATE TABLE t (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY);5. Backticks vs double quotes
-- MySQLSELECT `column` FROM `table`;
-- HeliosDBSELECT "column" FROM "table";Connection String
# MySQLmysql://user:pass@host:3306/dbname
# HeliosDB (use PostgreSQL format)postgresql://user:pass@host:5432/dbnameMigration from Oracle
Data Type Mapping
| Oracle | HeliosDB | Notes |
|---|---|---|
NUMBER(p) | NUMERIC(p) | Exact |
NUMBER | DOUBLE PRECISION | Float |
VARCHAR2(n) | VARCHAR(n) | Same |
CLOB | TEXT | Unlimited |
BLOB | BYTEA | Binary |
DATE | TIMESTAMP | Includes time |
TIMESTAMP | TIMESTAMP | Same |
RAW | BYTEA | Binary |
ROWID | N/A | Not supported |
SQL Syntax Differences
1. Dual table
-- OracleSELECT SYSDATE FROM DUAL;
-- HeliosDBSELECT NOW(); -- No FROM clause needed2. Outer join syntax
-- Oracle (old syntax)SELECT * FROM a, b WHERE a.id = b.id(+);
-- HeliosDBSELECT * FROM a LEFT JOIN b ON a.id = b.id;3. NVL vs COALESCE
-- OracleSELECT NVL(column, 'default') FROM table;
-- HeliosDBSELECT COALESCE(column, 'default') FROM table;4. DECODE vs CASE
-- OracleSELECT DECODE(status, 1, 'Active', 2, 'Inactive', 'Unknown') FROM t;
-- HeliosDBSELECT CASE status WHEN 1 THEN 'Active' WHEN 2 THEN 'Inactive' ELSE 'Unknown'END FROM t;5. Sequences
-- OracleCREATE SEQUENCE seq START WITH 1;SELECT seq.NEXTVAL FROM DUAL;
-- HeliosDBCREATE SEQUENCE seq START WITH 1;SELECT nextval('seq');6. Hierarchical queries
-- OracleSELECT * FROM emp START WITH mgr IS NULL CONNECT BY PRIOR emp_id = mgr;
-- HeliosDB (recursive CTE)WITH RECURSIVE emp_tree AS ( SELECT * FROM emp WHERE mgr IS NULL UNION ALL SELECT e.* FROM emp e JOIN emp_tree t ON e.mgr = t.emp_id)SELECT * FROM emp_tree;Migration from SQL Server
Data Type Mapping
| SQL Server | HeliosDB | Notes |
|---|---|---|
BIT | BOOLEAN | TRUE/FALSE |
TINYINT | SMALLINT | Wider |
MONEY | NUMERIC(19,4) | Exact |
DATETIME | TIMESTAMP | Standard |
DATETIME2 | TIMESTAMP | Standard |
NVARCHAR | VARCHAR | UTF-8 |
NTEXT | TEXT | UTF-8 |
VARBINARY | BYTEA | Binary |
UNIQUEIDENTIFIER | UUID | UUID type |
XML | TEXT or JSONB | Store as text |
SQL Syntax Differences
1. TOP vs LIMIT
-- SQL ServerSELECT TOP 10 * FROM users;
-- HeliosDBSELECT * FROM users LIMIT 10;2. String functions
-- SQL ServerSELECT LEN(column), CHARINDEX('a', column) FROM t;
-- HeliosDBSELECT LENGTH(column), POSITION('a' IN column) FROM t;3. Date functions
-- SQL ServerSELECT GETDATE(), DATEADD(day, 1, GETDATE());
-- HeliosDBSELECT NOW(), NOW() + INTERVAL '1 day';4. Identity columns
-- SQL ServerCREATE TABLE t (id INT IDENTITY(1,1) PRIMARY KEY);
-- HeliosDBCREATE TABLE t (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY);5. Square brackets
-- SQL ServerSELECT [column] FROM [table];
-- HeliosDBSELECT "column" FROM "table";Migration from MongoDB
Document to Relational Mapping
1. Embedded documents -> Separate tables
// MongoDB{ _id: ObjectId("..."), name: "John", address: { street: "123 Main St", city: "Boston" }}-- HeliosDB Option 1: JSONB columnCREATE TABLE users ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name VARCHAR(255), address JSONB);
-- HeliosDB Option 2: NormalizedCREATE TABLE users ( id UUID PRIMARY KEY, name VARCHAR(255));CREATE TABLE addresses ( id UUID PRIMARY KEY, user_id UUID REFERENCES users(id), street VARCHAR(255), city VARCHAR(255));2. Arrays -> Array types or junction tables
// MongoDB{ _id: ..., tags: ["tech", "news"] }-- HeliosDB Option 1: Array typeCREATE TABLE articles ( id UUID PRIMARY KEY, tags TEXT[]);
-- QuerySELECT * FROM articles WHERE 'tech' = ANY(tags);3. ObjectId -> UUID
-- Use native UUID typeCREATE TABLE documents ( id UUID PRIMARY KEY DEFAULT gen_random_uuid());Query Translation
| MongoDB | HeliosDB |
|---|---|
db.c.find({}) | SELECT * FROM c |
db.c.find({a: 1}) | SELECT * FROM c WHERE a = 1 |
db.c.find({a: {$gt: 1}}) | SELECT * FROM c WHERE a > 1 |
db.c.find({a: {$in: [1,2]}}) | SELECT * FROM c WHERE a IN (1, 2) |
db.c.find({a: {$regex: 'pat'}}) | SELECT * FROM c WHERE a ~ 'pat' |
db.c.aggregate([{$group: ...}]) | SELECT ... GROUP BY ... |
Schema Migration
Using ETL Pipeline
use heliosdb_etl::AutomatedETLEngine;
async fn migrate_schema() -> Result<()> { let engine = AutomatedETLEngine::new(Default::default()).await?;
// Extract sample data from source let source_data = extract_from_source("source_connection").await?;
// Infer schema let schema = engine.infer_schema("target_table", &source_data).await?;
// Review and adjust schema let adjusted_schema = review_schema(schema);
// Create table in HeliosDB create_table(adjusted_schema).await?;
Ok(())}Manual Schema Conversion
-- Example: Convert MySQL schema to HeliosDB
-- Original (MySQL)CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, email VARCHAR(255) NOT NULL UNIQUE, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, metadata JSON);
-- Converted (HeliosDB)CREATE TABLE users ( id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, email VARCHAR(255) NOT NULL UNIQUE, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), metadata JSONB);Data Migration
Bulk Load with COPY
-- Export from source (PostgreSQL example)COPY users TO '/tmp/users.csv' WITH CSV HEADER;
-- Import to HeliosDBCOPY users FROM '/tmp/users.csv' WITH CSV HEADER;Using ETL Pipeline
use heliosdb_etl::{AutomatedETLEngine, CDCProcessor};
async fn migrate_data() -> Result<()> { let engine = AutomatedETLEngine::new(Default::default()).await?;
// Build pipeline let pipeline = engine.build_pipeline(source_schema, target_schema).await?;
// Stream data while let Some(batch) = read_batch().await? { let result = pipeline.execute(batch).await?; write_to_heliosdb(result).await?; }
Ok(())}Query Migration
Query Validation Tool
# Compare query results between source and target
import psycopg2
def validate_query(source_conn, target_conn, query): source_cursor = source_conn.cursor() target_cursor = target_conn.cursor()
source_cursor.execute(query) target_cursor.execute(query)
source_results = source_cursor.fetchall() target_results = target_cursor.fetchall()
assert source_results == target_results, "Results differ!" print(f"Query validated: {len(source_results)} rows match")Testing and Validation
Data Validation Checklist
- Row counts match between source and target
- Sample data spot checks pass
- Foreign key relationships preserved
- Null handling correct
- Date/time conversions accurate
- Unicode data preserved
- Numeric precision maintained
Performance Validation
-- Run benchmark queriesEXPLAIN ANALYZE SELECT * FROM users WHERE email = 'test@example.com';
-- Compare with source database performanceApplication Testing
- Unit tests: Run existing test suite against HeliosDB
- Integration tests: Test all application flows
- Load tests: Verify performance under load
- Failover tests: Test high availability
Related Documentation
- README.md - SQL interface overview
- COMPATIBILITY_MATRIX.md - SQL compliance
- SQL_COMMAND_EXTENSIONS.md - HeliosDB extensions
- Automated ETL - ETL pipeline for migration