Skip to content

IBM DB2 to HeliosDB Migration Guide

IBM DB2 to HeliosDB Migration Guide

Version: 1.0 Last Updated: January 2026 Compatibility Target: IBM DB2 LUW 10.5, 11.1, 11.5


Table of Contents

  1. Introduction
  2. DRDA Wire Protocol Compatibility
  3. Pre-Migration Assessment
  4. Connection String Migration
  5. Data Type Mapping
  6. SQL Dialect Differences
  7. Stored Procedure Migration
  8. DB2 EXPORT/IMPORT to HeliosDB COPY
  9. Application Connectivity
  10. Performance Considerations
  11. Troubleshooting Common Issues
  12. Post-Migration Validation

1. Introduction

1.1 Why Migrate from DB2 to HeliosDB?

Organizations are increasingly migrating from IBM DB2 to HeliosDB for several compelling reasons:

Cost Savings

Cost FactorIBM DB2HeliosDBSavings
Processor License (Enterprise)$32,500/coreOpen pricing55-75%
Annual Support (SWMA)20% of licenseIncluded100%
pureScale/HADRAdditional licenseBuilt-in100%
Partitioning Feature$15,000/coreIncluded100%
Advanced Compression$12,000/coreIncluded100%
Database Encryption$10,000/coreIncluded100%

Typical 4-year TCO Reduction: 60-80%

Multi-Model Support

HeliosDB provides native support for multiple data models through a single platform:

  • Relational SQL: Full DB2 SQL compatibility
  • Document/JSON: MongoDB-compatible document storage
  • Key-Value: Redis-compatible operations
  • Time-Series: Native time-series optimizations
  • Graph: Cypher query language support
  • Vector: AI/ML embeddings with similarity search

Modern Architecture Advantages

CapabilityIBM DB2HeliosDB
Cloud-NativePartialFull Kubernetes support
Multi-ProtocolDB2 only9+ protocols
Auto-ScalingManualAutomatic
Self-HealingManual interventionAI-driven autonomous
ML IntegrationExternal toolsNative in-database ML
HTAPSeparate workloadsUnified workload

1.2 Migration Goals

This guide helps you achieve:

  1. Zero data loss during migration
  2. Minimal downtime through parallel operation strategies
  3. Application compatibility with existing DB2 clients via DRDA protocol
  4. Performance parity or improvement post-migration
  5. Reduced operational complexity through HeliosDB automation

2. DRDA Wire Protocol Compatibility

2.1 DRDA Protocol Support

HeliosDB implements the Distributed Relational Database Architecture (DRDA) protocol, enabling seamless connectivity from DB2 clients:

DRDA LevelCoverageFeatures
Level 3100%Basic operations, EXCSAT, ACCRDB
Level 4100%Extended features, cursors
Level 590%Advanced features

2.2 Connection Parameters

ParameterDB2 DefaultHeliosDB DefaultNotes
Port5000050000DRDA port
Database-heliosdbDatabase name
AuthenticationPasswordPassword, KerberosMultiple options
EncryptionSSL/TLSSSL/TLSFull encryption support

2.3 Supported DRDA Commands

CommandStatusDescription
EXCSATSupportedExchange server attributes
EXCSATRDSupportedExchange server attributes reply
ACCRDBSupportedAccess database
ACCRDBRMSupportedAccess reply message
SECCHKSupportedSecurity check
SECCHKRMSupportedSecurity reply
PRPSQLSTTSupportedPrepare SQL statement
EXCSQLSTTSupportedExecute SQL statement
OPNQRYSupportedOpen query
CNTQRYSupportedContinue query
CLSQRYSupportedClose query
SQLSTTSupportedSQL statement text
COMMITSupportedCommit transaction
ROLLBACKSupportedRollback transaction

2.4 Wire Protocol Compatibility

Default Port: 50000
Protocol: DRDA (Distributed Relational Database Architecture)
Wire Format: DRDA Level 5 compatible
Character Set: UTF-8, EBCDIC supported

Supported DB2 Drivers:

DriverMinimum VersionStatus
IBM DB2 Driver for JDBC11.5+Full compatibility
JDBC Type 44.xFull compatibility
IBM DB2 ODBC11.xFull compatibility
ibm_db (Python)3.xFull compatibility
IBM.Data.DB2 (.NET)11.xFull compatibility
IBM.Data.DB2.Core (.NET Core)3.xFull compatibility

3. Pre-Migration Assessment

3.1 Database Inventory

Before migration, perform a comprehensive inventory of your DB2 environment.

Schema Analysis Script

-- Database size summary
SELECT
TABSCHEMA AS schema_name,
TABNAME AS table_name,
NPAGES * 4 / 1024 AS size_mb,
CARD AS row_count
FROM SYSCAT.TABLES
WHERE TABSCHEMA NOT LIKE 'SYS%'
AND TYPE = 'T'
ORDER BY NPAGES DESC
FETCH FIRST 50 ROWS ONLY;
-- Schema object counts
SELECT
TABSCHEMA,
COUNT(CASE WHEN TYPE = 'T' THEN 1 END) AS tables,
COUNT(CASE WHEN TYPE = 'V' THEN 1 END) AS views,
COUNT(CASE WHEN TYPE = 'A' THEN 1 END) AS aliases
FROM SYSCAT.TABLES
WHERE TABSCHEMA NOT LIKE 'SYS%'
GROUP BY TABSCHEMA
ORDER BY tables DESC;
-- Index summary
SELECT
INDSCHEMA,
COUNT(*) AS index_count,
SUM(NLEAF * 4 / 1024) AS total_size_mb
FROM SYSCAT.INDEXES
WHERE INDSCHEMA NOT LIKE 'SYS%'
GROUP BY INDSCHEMA
ORDER BY index_count DESC;

3.2 Stored Procedure Analysis

Analyze your SQL PL codebase for migration complexity:

-- Count routine objects by type
SELECT
ROUTINESCHEMA,
ROUTINETYPE,
COUNT(*) AS routine_count,
SUM(CASE WHEN VALID = 'Y' THEN 1 ELSE 0 END) AS valid_count,
SUM(CASE WHEN VALID = 'N' THEN 1 ELSE 0 END) AS invalid_count
FROM SYSCAT.ROUTINES
WHERE ROUTINESCHEMA NOT LIKE 'SYS%'
AND LANGUAGE = 'SQL'
GROUP BY ROUTINESCHEMA, ROUTINETYPE
ORDER BY routine_count DESC;
-- Procedure source code length
SELECT
ROUTINESCHEMA,
ROUTINENAME,
ROUTINETYPE,
LENGTH(TEXT) AS source_length
FROM SYSCAT.ROUTINES
WHERE ROUTINESCHEMA NOT LIKE 'SYS%'
AND TEXT IS NOT NULL
ORDER BY source_length DESC
FETCH FIRST 20 ROWS ONLY;
-- External routine dependencies
SELECT
ROUTINESCHEMA,
ROUTINENAME,
LANGUAGE,
EXTERNAL_NAME
FROM SYSCAT.ROUTINES
WHERE ROUTINESCHEMA NOT LIKE 'SYS%'
AND LANGUAGE IN ('C', 'JAVA', 'CLR')
ORDER BY ROUTINESCHEMA, ROUTINENAME;

3.3 Feature Usage Inventory

-- Check for DB2-specific features
-- MQT (Materialized Query Tables)
SELECT TABSCHEMA, TABNAME, REFRESH
FROM SYSCAT.TABLES
WHERE TYPE = 'S' -- Summary table
AND TABSCHEMA NOT LIKE 'SYS%';
-- Range partitioned tables
SELECT TABSCHEMA, TABNAME, DATAPARTITIONKEYSEQ
FROM SYSCAT.DATAPARTITIONEXPRESSION
WHERE TABSCHEMA NOT LIKE 'SYS%';
-- Check for XML columns
SELECT TABSCHEMA, TABNAME, COLNAME
FROM SYSCAT.COLUMNS
WHERE TYPENAME = 'XML'
AND TABSCHEMA NOT LIKE 'SYS%';
-- User-defined types
SELECT TYPESCHEMA, TYPENAME, METATYPE, SOURCENAME
FROM SYSCAT.DATATYPES
WHERE TYPESCHEMA NOT LIKE 'SYS%';
-- Sequences
SELECT SEQSCHEMA, SEQNAME, START, INCREMENT, CACHE
FROM SYSCAT.SEQUENCES
WHERE SEQSCHEMA NOT LIKE 'SYS%';

3.4 Application Dependencies

Document all applications connecting to DB2:

-- Active application snapshots
SELECT
APPLICATION_NAME,
CLIENT_USERID,
CLIENT_WRKSTNNAME,
CLIENT_APPLNAME,
CLIENT_PROTOCOL,
COUNT(*) AS connection_count
FROM SYSIBMADM.SNAPAPPL_INFO
GROUP BY APPLICATION_NAME, CLIENT_USERID, CLIENT_WRKSTNNAME,
CLIENT_APPLNAME, CLIENT_PROTOCOL
ORDER BY connection_count DESC;

3.5 Migration Complexity Score

Calculate your migration complexity:

FactorPointsYour Score
Tables < 501
Tables 50-2002
Tables > 2003
SQL Procedures < 501
SQL Procedures 50-2002
SQL Procedures > 2003
No external routines (C/Java)0
Uses external routines3
No pureScale/HADR0
Uses pureScale2
No XML columns0
Uses XML extensively2

Total Score Interpretation:

  • 1-4: Simple migration (1-2 weeks)
  • 5-8: Medium complexity (2-6 weeks)
  • 9+: Complex migration (6+ weeks)

4. Connection String Migration

4.1 DB2 CLP to HeliosDB

DB2 Command Line Processor:

Terminal window
# DB2 CLP connection
db2 connect to MYDB user db2admin using password
# HeliosDB via DRDA (identical syntax)
db2 connect to heliosdb user admin using password

4.2 Catalog Configuration

DB2 Node and Database Catalog:

Terminal window
# DB2: Catalog remote node
db2 catalog tcpip node HELIOS_NODE remote heliosdb-server server 50000
db2 catalog database heliosdb as HELIOSDB at node HELIOS_NODE
# Connect using catalog alias
db2 connect to HELIOSDB user admin using password

db2cli.ini Configuration:

[heliosdb]
Database=heliosdb
Protocol=TCPIP
Hostname=heliosdb-server
ServiceName=50000
UID=admin
PWD=password
CurrentSchema=myschema

4.3 JDBC Connection Strings

DB2 JDBC Type 4:

// DB2 connection
String db2Url = "jdbc:db2://db2-server:50000/MYDB";
// HeliosDB connection (same driver works)
String heliosUrl = "jdbc:db2://heliosdb-server:50000/heliosdb";
// With connection properties
String heliosUrlFull = "jdbc:db2://heliosdb-server:50000/heliosdb:" +
"currentSchema=myschema;" +
"securityMechanism=3;" + // Clear text password
"sslConnection=true;";

4.4 ODBC DSN Configuration

Windows ODBC (odbc.ini):

[HeliosDB_DSN]
Description=HeliosDB via DRDA
Driver=IBM DB2 ODBC DRIVER
Database=heliosdb
Hostname=heliosdb-server
Port=50000
Protocol=TCPIP
UID=admin
PWD=password

Linux unixODBC (odbcinst.ini):

[IBM DB2 ODBC DRIVER]
Description=IBM DB2 ODBC Driver
Driver=/opt/ibm/db2/V11.5/lib64/libdb2o.so
[HeliosDB]
Driver=IBM DB2 ODBC DRIVER
Database=heliosdb
Hostname=heliosdb-server
Port=50000
Protocol=TCPIP

5. Data Type Mapping

5.1 Numeric Types

DB2 TypeHeliosDB TypeNotes
SMALLINTSMALLINT2-byte integer, direct mapping
INTEGERINTEGER4-byte integer, direct mapping
BIGINTBIGINT8-byte integer, direct mapping
DECIMAL(p,s)DECIMAL(p,s)Fixed precision, direct mapping
NUMERIC(p,s)NUMERIC(p,s)Same as DECIMAL
REALREAL4-byte float
DOUBLEDOUBLE8-byte float
DECFLOAT(16)DECFLOAT(16)IEEE 754-2008 decimal
DECFLOAT(34)DECFLOAT(34)Extended decimal float

5.2 Character Types

DB2 TypeHeliosDB TypeNotes
CHAR(n)CHAR(n)Fixed length, max 254
VARCHAR(n)VARCHAR(n)Variable length, max 32672
LONG VARCHARVARCHAR(32700)Deprecated, use VARCHAR
CLOB(n)CLOB(n)Character LOB, up to 2GB
GRAPHIC(n)CHAR(n)Double-byte characters
VARGRAPHIC(n)VARCHAR(n)Variable double-byte
DBCLOB(n)CLOB(n)Double-byte CLOB

5.3 Binary Types

DB2 TypeHeliosDB TypeNotes
CHAR(n) FOR BIT DATABINARY(n)Fixed binary
VARCHAR(n) FOR BIT DATAVARBINARY(n)Variable binary
BLOB(n)BLOB(n)Binary LOB, up to 2GB
BINARY(n)BINARY(n)DB2 11.1+
VARBINARY(n)VARBINARY(n)DB2 11.1+

5.4 Date/Time Types

DB2 TypeHeliosDB TypeNotes
DATEDATECalendar date
TIMETIMETime of day
TIMESTAMPTIMESTAMPDate and time
TIMESTAMP(p)TIMESTAMP(p)Fractional seconds precision

5.5 Special Types

DB2 TypeHeliosDB TypeNotes
BOOLEANBOOLEANDB2 11.1+
XMLJSONBConvert to JSON
ROW typeRECORDComposite types
ARRAYARRAYCollection type

5.6 Data Type Conversion Script

-- Generate column type conversion report
SELECT
c.TABSCHEMA,
c.TABNAME,
c.COLNAME,
c.TYPENAME AS db2_type,
c.LENGTH,
c.SCALE,
CASE c.TYPENAME
WHEN 'LONG VARCHAR' THEN 'VARCHAR(32700)'
WHEN 'GRAPHIC' THEN 'CHAR(' || c.LENGTH/2 || ')'
WHEN 'VARGRAPHIC' THEN 'VARCHAR(' || c.LENGTH/2 || ')'
WHEN 'DBCLOB' THEN 'CLOB'
WHEN 'XML' THEN 'JSONB'
ELSE c.TYPENAME
END AS helios_type
FROM SYSCAT.COLUMNS c
WHERE c.TABSCHEMA NOT LIKE 'SYS%'
AND c.TYPENAME IN ('LONG VARCHAR', 'GRAPHIC', 'VARGRAPHIC', 'DBCLOB', 'XML')
ORDER BY c.TABSCHEMA, c.TABNAME, c.COLNO;

6. SQL Dialect Differences

6.1 Pagination and Row Limiting

DB2 Syntax (fully supported in HeliosDB):

-- FETCH FIRST N ROWS ONLY
SELECT * FROM employees
ORDER BY hire_date DESC
FETCH FIRST 10 ROWS ONLY;
-- OFFSET with FETCH
SELECT * FROM employees
ORDER BY emp_id
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;
-- FETCH with PERCENT
SELECT * FROM employees
ORDER BY salary DESC
FETCH FIRST 10 PERCENT ROWS ONLY;

6.2 Isolation Levels

DB2 Lock Hints (supported):

-- Uncommitted read
SELECT * FROM employees WITH UR;
-- Cursor stability
SELECT * FROM employees WITH CS;
-- Read stability
SELECT * FROM employees WITH RS;
-- Repeatable read
SELECT * FROM employees WITH RR;

6.3 Special Registers

DB2 RegisterHeliosDB EquivalentNotes
CURRENT DATECURRENT DATEDirect support
CURRENT TIMECURRENT TIMEDirect support
CURRENT TIMESTAMPCURRENT TIMESTAMPDirect support
CURRENT USERCURRENT_USERStandard SQL
CURRENT SCHEMACURRENT_SCHEMADirect support
CURRENT PATHCURRENT_PATHDirect support

Example:

-- Both work identically
SELECT CURRENT DATE, CURRENT TIME, CURRENT TIMESTAMP FROM SYSIBM.SYSDUMMY1;
-- HeliosDB alternative (no SYSDUMMY1 needed)
SELECT CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP;

6.4 MERGE Statement

DB2 MERGE (fully supported):

MERGE INTO target_table t
USING source_table s
ON t.id = s.id
WHEN MATCHED THEN
UPDATE SET
t.name = s.name,
t.updated_at = CURRENT TIMESTAMP
WHEN NOT MATCHED THEN
INSERT (id, name, created_at)
VALUES (s.id, s.name, CURRENT TIMESTAMP);

6.5 Recursive CTEs

DB2 Recursive Query (fully supported):

WITH org_hierarchy (emp_id, emp_name, manager_id, level) AS (
-- Anchor member
SELECT emp_id, emp_name, manager_id, 1
FROM employees
WHERE manager_id IS NULL
UNION ALL
-- Recursive member
SELECT e.emp_id, e.emp_name, e.manager_id, h.level + 1
FROM employees e
JOIN org_hierarchy h ON e.manager_id = h.emp_id
)
SELECT * FROM org_hierarchy
ORDER BY level, emp_name;

6.6 OLAP Functions

DB2 Window Functions (fully supported):

SELECT
emp_id,
department_id,
salary,
ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rank_in_dept,
SUM(salary) OVER (PARTITION BY department_id) AS dept_total,
AVG(salary) OVER (ORDER BY hire_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg
FROM employees;

6.7 Identity Columns

DB2 Identity (fully supported):

-- DB2 identity column
CREATE TABLE orders (
order_id INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY
(START WITH 1 INCREMENT BY 1),
order_date DATE,
amount DECIMAL(10,2)
);
-- HeliosDB (identical syntax supported)
CREATE TABLE orders (
order_id INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY
(START WITH 1 INCREMENT BY 1),
order_date DATE,
amount DECIMAL(10,2)
);

6.8 Sequence Objects

-- Create sequence (identical syntax)
CREATE SEQUENCE order_seq
AS INTEGER
START WITH 1000
INCREMENT BY 1
MINVALUE 1
MAXVALUE 999999999
CYCLE
CACHE 100;
-- Use sequence
INSERT INTO orders (order_id, order_date)
VALUES (NEXT VALUE FOR order_seq, CURRENT DATE);
-- Query current value
SELECT PREVIOUS VALUE FOR order_seq FROM SYSIBM.SYSDUMMY1;

6.9 DB2-Specific Functions Mapping

DB2 FunctionHeliosDB FunctionNotes
DAYS(date)DAYS(date)Days since 0001-01-01
MIDNIGHT_SECONDS(time)MIDNIGHT_SECONDS(time)Seconds since midnight
TIMESTAMPDIFF(interval, t1, t2)TIMESTAMPDIFF(interval, t1, t2)Time difference
VARCHAR_FORMAT(ts, fmt)TO_CHAR(ts, fmt)Date formatting
TIMESTAMP_FORMAT(str, fmt)TO_TIMESTAMP(str, fmt)String to timestamp
RAISE_ERROR(code, msg)SIGNAL SQLSTATEError signaling
COALESCE(a, b, c)COALESCE(a, b, c)First non-null
NULLIF(a, b)NULLIF(a, b)Null if equal
VALUE(a, b)COALESCE(a, b)DB2 alias for COALESCE
POSSTR(str, search)POSITION(search IN str)Find position
SUBSTR(str, pos, len)SUBSTR(str, pos, len)Substring
STRIP(str)TRIM(str)Remove whitespace
DIGITS(num)LPAD(num::text, n, ‘0’)Number to string

7. Stored Procedure Migration

7.1 SQL Procedure Compatibility

HeliosDB provides 85% compatibility with DB2 SQL PL procedures:

Basic Procedure Structure

-- DB2 SQL Procedure (fully supported)
CREATE OR REPLACE PROCEDURE update_salary (
IN p_emp_id INTEGER,
IN p_increase DECIMAL(5,2),
OUT p_new_salary DECIMAL(10,2)
)
LANGUAGE SQL
BEGIN
DECLARE v_current_salary DECIMAL(10,2);
SELECT salary INTO v_current_salary
FROM employees
WHERE emp_id = p_emp_id;
SET p_new_salary = v_current_salary * (1 + p_increase / 100);
UPDATE employees
SET salary = p_new_salary
WHERE emp_id = p_emp_id;
END

7.2 Control Flow Statements

CREATE OR REPLACE PROCEDURE process_order (
IN p_order_id INTEGER,
OUT p_status VARCHAR(50)
)
LANGUAGE SQL
BEGIN
DECLARE v_total DECIMAL(12,2);
DECLARE v_customer_type VARCHAR(20);
-- IF-THEN-ELSEIF-ELSE
SELECT total_amount, customer_type
INTO v_total, v_customer_type
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id
WHERE o.order_id = p_order_id;
IF v_total > 10000 THEN
SET p_status = 'HIGH_VALUE';
ELSEIF v_total > 1000 THEN
SET p_status = 'MEDIUM_VALUE';
ELSE
SET p_status = 'LOW_VALUE';
END IF;
-- CASE statement
SET p_status = p_status || ' - ' ||
CASE v_customer_type
WHEN 'PREMIUM' THEN 'PRIORITY'
WHEN 'STANDARD' THEN 'NORMAL'
ELSE 'BASIC'
END;
END

7.3 Cursor Operations

CREATE OR REPLACE PROCEDURE process_pending_orders ()
LANGUAGE SQL
BEGIN
DECLARE v_order_id INTEGER;
DECLARE v_amount DECIMAL(12,2);
DECLARE v_end_of_cursor INTEGER DEFAULT 0;
-- Declare cursor
DECLARE order_cursor CURSOR FOR
SELECT order_id, total_amount
FROM orders
WHERE status = 'PENDING'
ORDER BY created_at;
-- Handler for end of cursor
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET v_end_of_cursor = 1;
OPEN order_cursor;
fetch_loop: LOOP
FETCH order_cursor INTO v_order_id, v_amount;
IF v_end_of_cursor = 1 THEN
LEAVE fetch_loop;
END IF;
-- Process order
UPDATE orders
SET status = 'PROCESSING',
processed_at = CURRENT TIMESTAMP
WHERE order_id = v_order_id;
END LOOP fetch_loop;
CLOSE order_cursor;
END

7.4 Exception Handling

CREATE OR REPLACE PROCEDURE transfer_funds (
IN p_from_account INTEGER,
IN p_to_account INTEGER,
IN p_amount DECIMAL(12,2),
OUT p_result VARCHAR(100)
)
LANGUAGE SQL
BEGIN
DECLARE v_balance DECIMAL(12,2);
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
SET p_result = 'ERROR: Transaction failed - ' || SQLERRM;
END;
DECLARE EXIT HANDLER FOR SQLSTATE '45001'
BEGIN
ROLLBACK;
SET p_result = 'ERROR: Insufficient funds';
END;
-- Check balance
SELECT balance INTO v_balance
FROM accounts
WHERE account_id = p_from_account;
IF v_balance < p_amount THEN
SIGNAL SQLSTATE '45001';
END IF;
-- Perform transfer
UPDATE accounts SET balance = balance - p_amount
WHERE account_id = p_from_account;
UPDATE accounts SET balance = balance + p_amount
WHERE account_id = p_to_account;
COMMIT;
SET p_result = 'SUCCESS: Transferred ' || p_amount;
END

7.5 User-Defined Functions

-- Scalar function
CREATE OR REPLACE FUNCTION calculate_tax (
p_amount DECIMAL(12,2),
p_rate DECIMAL(5,2)
)
RETURNS DECIMAL(12,2)
LANGUAGE SQL
DETERMINISTIC
NO EXTERNAL ACTION
CONTAINS SQL
BEGIN
RETURN p_amount * (p_rate / 100);
END
-- Table function
CREATE OR REPLACE FUNCTION get_department_employees (
p_dept_id INTEGER
)
RETURNS TABLE (
emp_id INTEGER,
emp_name VARCHAR(100),
salary DECIMAL(10,2)
)
LANGUAGE SQL
READS SQL DATA
BEGIN
RETURN
SELECT emp_id, emp_name, salary
FROM employees
WHERE department_id = p_dept_id;
END

7.6 Triggers

-- BEFORE trigger
CREATE OR REPLACE TRIGGER emp_before_insert
BEFORE INSERT ON employees
REFERENCING NEW AS n
FOR EACH ROW
BEGIN ATOMIC
SET n.created_at = CURRENT TIMESTAMP;
SET n.updated_at = CURRENT TIMESTAMP;
SET n.emp_name = UPPER(n.emp_name);
END
-- AFTER trigger
CREATE OR REPLACE TRIGGER emp_audit_trigger
AFTER UPDATE ON employees
REFERENCING OLD AS o NEW AS n
FOR EACH ROW
BEGIN ATOMIC
INSERT INTO employee_audit (
emp_id, action, old_salary, new_salary, changed_at, changed_by
) VALUES (
n.emp_id, 'UPDATE', o.salary, n.salary, CURRENT TIMESTAMP, CURRENT USER
);
END
-- Statement trigger
CREATE OR REPLACE TRIGGER orders_batch_trigger
AFTER INSERT ON orders
REFERENCING NEW TABLE AS inserted
FOR EACH STATEMENT
BEGIN ATOMIC
INSERT INTO order_statistics (batch_date, order_count, total_amount)
SELECT CURRENT DATE, COUNT(*), SUM(amount)
FROM inserted;
END

7.7 External Procedure Conversion

DB2 External Procedures (C, Java, CLR) require conversion to SQL procedures or HeliosDB extensions:

-- DB2 external procedure (Java)
CREATE PROCEDURE java_proc (IN p_input VARCHAR(100))
EXTERNAL NAME 'com.example.MyClass.myMethod'
LANGUAGE JAVA
PARAMETER STYLE JAVA;
-- HeliosDB conversion: SQL procedure or extension
CREATE OR REPLACE PROCEDURE converted_proc (IN p_input VARCHAR(100))
LANGUAGE SQL
BEGIN
-- Re-implement logic in SQL
-- Or use HeliosDB extension framework
END

8. DB2 EXPORT/IMPORT to HeliosDB COPY

8.1 Basic Data Export from DB2

DB2 EXPORT Command:

Terminal window
# Export to IXF format (preserves types)
db2 "EXPORT TO employees.ixf OF IXF
SELECT * FROM employees"
# Export to DEL format (CSV-like)
db2 "EXPORT TO employees.csv OF DEL
MODIFIED BY COLDEL, CHARDEL\"\" DECPT.
SELECT * FROM employees"
# Export with column headers
db2 "EXPORT TO employees.csv OF DEL
MODIFIED BY NOCHARDEL COLHDRS
SELECT * FROM employees"

8.2 HeliosDB COPY Command

Import CSV to HeliosDB:

-- Basic COPY from CSV
COPY employees FROM '/path/to/employees.csv'
WITH (FORMAT csv, HEADER true);
-- With options
COPY employees FROM '/path/to/employees.csv'
WITH (
FORMAT csv,
HEADER true,
DELIMITER ',',
NULL '',
QUOTE '"',
ESCAPE '\\'
);
-- COPY specific columns
COPY employees (emp_id, emp_name, department_id, salary)
FROM '/path/to/employees.csv'
WITH (FORMAT csv, HEADER true);

8.3 Large Table Migration Strategy

Step 1: Export from DB2 with partitioning:

#!/bin/bash
# Export large table in chunks
TABLE="large_orders"
CHUNK_SIZE=1000000
for i in $(seq 0 9); do
db2 "EXPORT TO ${TABLE}_part${i}.csv OF DEL
MODIFIED BY NOCHARDEL
SELECT * FROM ${TABLE}
WHERE MOD(order_id, 10) = ${i}"
done

Step 2: Parallel import to HeliosDB:

-- Create staging table
CREATE TABLE orders_staging (LIKE orders INCLUDING ALL);
-- Parallel COPY (run concurrently)
COPY orders_staging FROM '/path/to/large_orders_part0.csv' WITH (FORMAT csv);
COPY orders_staging FROM '/path/to/large_orders_part1.csv' WITH (FORMAT csv);
-- ... continue for all parts
-- Swap tables
ALTER TABLE orders RENAME TO orders_old;
ALTER TABLE orders_staging RENAME TO orders;
DROP TABLE orders_old;

8.4 LOB Data Migration

DB2 LOB Export:

Terminal window
# Export with LOBs to separate files
db2 "EXPORT TO documents.csv OF DEL
LOBS TO /lob_data/
LOBFILE documents
MODIFIED BY LOBSINFILE
SELECT doc_id, doc_content FROM documents"

HeliosDB LOB Import:

-- Create table with LOB column
CREATE TABLE documents (
doc_id INTEGER PRIMARY KEY,
doc_content BYTEA
);
-- Import using pg_read_binary_file or application code
-- For large LOBs, use client-side import

8.5 Migration Validation Script

-- Generate row count comparison queries
SELECT
'SELECT ''' || TABNAME || ''' AS table_name, COUNT(*) AS row_count FROM ' ||
TABSCHEMA || '.' || TABNAME || ';'
FROM SYSCAT.TABLES
WHERE TABSCHEMA = 'MYSCHEMA'
AND TYPE = 'T'
ORDER BY TABNAME;

9. Application Connectivity

9.1 Java (JDBC) Configuration

Maven Dependency:

<dependency>
<groupId>com.ibm.db2</groupId>
<artifactId>jcc</artifactId>
<version>11.5.8.0</version>
</dependency>

Connection Example:

import java.sql.*;
import com.ibm.db2.jcc.DB2SimpleDataSource;
public class HeliosDBConnection {
public static void main(String[] args) throws SQLException {
// Simple connection
String url = "jdbc:db2://heliosdb-server:50000/heliosdb";
Connection conn = DriverManager.getConnection(url, "admin", "password");
// Using DataSource with connection pool
DB2SimpleDataSource ds = new DB2SimpleDataSource();
ds.setDatabaseName("heliosdb");
ds.setServerName("heliosdb-server");
ds.setPortNumber(50000);
ds.setUser("admin");
ds.setPassword("password");
ds.setCurrentSchema("myschema");
// SSL/TLS connection
ds.setSslConnection(true);
ds.setSslCertLocation("/path/to/cert.pem");
Connection pooledConn = ds.getConnection();
// Execute query
try (Statement stmt = pooledConn.createStatement();
ResultSet rs = stmt.executeQuery(
"SELECT * FROM employees FETCH FIRST 10 ROWS ONLY")) {
while (rs.next()) {
System.out.println(rs.getString("emp_name"));
}
}
}
}

Spring Boot Configuration:

application.yml
spring:
datasource:
url: jdbc:db2://heliosdb-server:50000/heliosdb
username: admin
password: password
driver-class-name: com.ibm.db2.jcc.DB2Driver
hikari:
maximum-pool-size: 20
minimum-idle: 5
connection-timeout: 30000

9.2 Python (ibm_db) Configuration

Installation:

Terminal window
pip install ibm_db ibm_db_sa

Connection Example:

import ibm_db
import ibm_db_dbi
# Direct connection
conn_string = (
"DATABASE=heliosdb;"
"HOSTNAME=heliosdb-server;"
"PORT=50000;"
"PROTOCOL=TCPIP;"
"UID=admin;"
"PWD=password;"
)
# ibm_db connection
ibm_db_conn = ibm_db.connect(conn_string, "", "")
# Execute query
stmt = ibm_db.exec_immediate(ibm_db_conn,
"SELECT * FROM employees FETCH FIRST 10 ROWS ONLY")
while ibm_db.fetch_row(stmt):
print(ibm_db.result(stmt, "EMP_NAME"))
ibm_db.close(ibm_db_conn)
# Using ibm_db_dbi (DB-API 2.0 compatible)
conn = ibm_db_dbi.connect(conn_string, "", "")
cursor = conn.cursor()
cursor.execute("SELECT emp_id, emp_name, salary FROM employees WHERE dept_id = ?", (10,))
for row in cursor.fetchall():
print(f"{row['EMP_ID']}: {row['EMP_NAME']}")
cursor.close()
conn.close()

SQLAlchemy Integration:

from sqlalchemy import create_engine, text
from sqlalchemy.orm import sessionmaker
# Connection URL
engine = create_engine(
"ibm_db_sa://admin:password@heliosdb-server:50000/heliosdb",
pool_size=10,
max_overflow=20,
pool_pre_ping=True
)
Session = sessionmaker(bind=engine)
session = Session()
# Execute query
result = session.execute(text("SELECT * FROM employees FETCH FIRST 10 ROWS ONLY"))
for row in result:
print(row)
session.close()

9.3 .NET Configuration

NuGet Package:

<PackageReference Include="IBM.Data.DB2.Core" Version="3.1.0.500" />

Connection Example:

using IBM.Data.DB2.Core;
using System;
class Program
{
static void Main()
{
string connString = @"
Server=heliosdb-server:50000;
Database=heliosdb;
UID=admin;
PWD=password;
CurrentSchema=myschema;";
using (DB2Connection conn = new DB2Connection(connString))
{
conn.Open();
using (DB2Command cmd = conn.CreateCommand())
{
cmd.CommandText = @"
SELECT emp_id, emp_name, salary
FROM employees
WHERE department_id = @deptId
FETCH FIRST 10 ROWS ONLY";
cmd.Parameters.Add("@deptId", DB2Type.Integer).Value = 10;
using (DB2DataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine($"{reader["emp_id"]}: {reader["emp_name"]}");
}
}
}
}
}
}

Entity Framework Core:

// DbContext configuration
public class AppDbContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseDb2("Server=heliosdb-server:50000;Database=heliosdb;UID=admin;PWD=password");
}
}

9.4 Node.js Configuration

Installation:

Terminal window
npm install ibm_db

Connection Example:

const ibmdb = require('ibm_db');
const connString =
"DATABASE=heliosdb;" +
"HOSTNAME=heliosdb-server;" +
"PORT=50000;" +
"PROTOCOL=TCPIP;" +
"UID=admin;" +
"PWD=password;";
// Async connection
ibmdb.open(connString, (err, conn) => {
if (err) {
console.error('Connection failed:', err);
return;
}
conn.query("SELECT * FROM employees FETCH FIRST 10 ROWS ONLY", (err, data) => {
if (err) {
console.error('Query failed:', err);
} else {
console.log(data);
}
conn.close(() => {
console.log('Connection closed');
});
});
});
// Using promises
async function queryEmployees() {
const conn = await ibmdb.open(connString);
try {
const result = await conn.query(
"SELECT emp_id, emp_name, salary FROM employees WHERE dept_id = ?",
[10]
);
return result;
} finally {
await conn.close();
}
}

10. Performance Considerations

10.1 Query Optimization Hints

DB2 Optimization Hints (supported):

-- Optimize for N rows
SELECT * FROM orders
WHERE customer_id = 123
OPTIMIZE FOR 1 ROW;
-- Optimize for all rows
SELECT * FROM orders
WHERE status = 'PENDING'
OPTIMIZE FOR ALL ROWS;
-- Force index usage
SELECT * FROM employees
WHERE department_id = 10
-- HeliosDB uses similar hint syntax

10.2 Statistics Collection

-- DB2 RUNSTATS equivalent in HeliosDB
ANALYZE employees;
-- Analyze specific columns
ANALYZE employees (department_id, salary);
-- Analyze with sampling (for large tables)
ANALYZE employees TABLESAMPLE SYSTEM (10);
-- View statistics
SELECT
schemaname,
tablename,
n_live_tup,
n_dead_tup,
last_analyze
FROM pg_stat_user_tables
WHERE tablename = 'employees';

10.3 Index Migration Best Practices

-- Identify key indexes from DB2
SELECT
INDSCHEMA,
INDNAME,
TABSCHEMA,
TABNAME,
COLNAMES,
UNIQUERULE,
INDEXTYPE
FROM SYSCAT.INDEXES
WHERE TABSCHEMA NOT LIKE 'SYS%'
ORDER BY NLEAF DESC
FETCH FIRST 20 ROWS ONLY;
-- Create equivalent indexes in HeliosDB
CREATE INDEX idx_emp_dept ON employees (department_id);
CREATE UNIQUE INDEX idx_emp_email ON employees (email);
-- Partial indexes (HeliosDB enhancement)
CREATE INDEX idx_active_orders ON orders (customer_id, order_date)
WHERE status = 'ACTIVE';

10.4 Connection Pooling

HikariCP Configuration (Java):

# Recommended pool settings
spring:
datasource:
hikari:
maximum-pool-size: 50
minimum-idle: 10
idle-timeout: 300000
max-lifetime: 1200000
connection-timeout: 30000
validation-timeout: 5000
leak-detection-threshold: 60000

10.5 Batch Operations

// Java batch insert
try (Connection conn = dataSource.getConnection()) {
conn.setAutoCommit(false);
String sql = "INSERT INTO orders (order_id, customer_id, amount) VALUES (?, ?, ?)";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
for (Order order : orders) {
pstmt.setInt(1, order.getId());
pstmt.setInt(2, order.getCustomerId());
pstmt.setBigDecimal(3, order.getAmount());
pstmt.addBatch();
if (batchCount++ % 1000 == 0) {
pstmt.executeBatch();
}
}
pstmt.executeBatch();
}
conn.commit();
}

10.6 HeliosDB Performance Features

FeatureDescriptionBenefit
Auto-IndexingML-based index recommendations30-50% query improvement
Adaptive ExecutionRuntime plan optimizationHandles data skew
Parallel QueryAutomatic parallelizationLinear scaling
Result CachingMulti-tier caching10-100x for repeated queries
Predicate PushdownFilter at storage layer3-10x faster scans

11. Troubleshooting Common Issues

11.1 Connection Issues

Error: SQL30081N (Communication Error)

Cause: Network connectivity or firewall issues

Solution:

Terminal window
# Verify network connectivity
telnet heliosdb-server 50000
ping heliosdb-server
# Check firewall
iptables -L -n | grep 50000
# Verify HeliosDB DRDA listener
heliosdb status --protocol drda

Error: SQL1403N (Authentication Failed)

Cause: Invalid credentials or authentication method mismatch

Solution:

Terminal window
# Test connection with different auth methods
db2 "CONNECT TO heliosdb USER admin USING 'password'"
# Check authentication configuration
cat /etc/heliosdb/heliosdb.toml | grep -A5 "\[drda\]"

11.2 SQL Syntax Issues

Error: SQL0206N (Column Not Found)

Cause: Case sensitivity differences

Solution:

-- DB2 is case-insensitive by default
-- HeliosDB may require exact case or double quotes
-- If column created as uppercase
SELECT "EMPLOYEE_NAME" FROM employees;
-- Or use case-insensitive schema setting
SET search_path TO myschema;

Error: SQL0204N (Object Not Found)

Cause: Schema not in search path

Solution:

-- Set current schema
SET CURRENT SCHEMA = myschema;
-- Or use fully qualified names
SELECT * FROM myschema.employees;
-- Check available schemas
SELECT schema_name FROM information_schema.schemata;

11.3 Data Type Issues

Error: SQL0420N (Character Conversion Error)

Cause: Character set mismatch

Solution:

Terminal window
# Verify database character set
db2 "SELECT CODEPAGE FROM SYSCAT.DATATYPES WHERE TYPENAME = 'VARCHAR'"
# HeliosDB uses UTF-8
# Convert data during export if needed
db2 "EXPORT TO data.csv OF DEL MODIFIED BY CODEPAGE=1208 ..."

Error: SQL0802N (Arithmetic Overflow)

Cause: Numeric precision differences

Solution:

-- Check column definitions
SELECT COLNAME, TYPENAME, LENGTH, SCALE
FROM SYSCAT.COLUMNS
WHERE TABNAME = 'MYTABLE';
-- Adjust column precision in HeliosDB
ALTER TABLE mytable ALTER COLUMN amount TYPE DECIMAL(15,2);

11.4 Performance Issues

Slow Query After Migration

Cause: Missing statistics or indexes

Solution:

-- Analyze all tables
ANALYZE;
-- Check for missing indexes
EXPLAIN ANALYZE SELECT ... ;
-- Review index recommendations
SELECT * FROM heliosdb_index_advisor WHERE table_name = 'orders';

High Memory Usage

Cause: Large result sets or inefficient queries

Solution:

-- Use pagination
SELECT * FROM large_table
FETCH FIRST 1000 ROWS ONLY;
-- Enable result streaming (in application)
statement.setFetchSize(1000);

11.5 Error Code Mapping

DB2 SQLCODEDescriptionHeliosDB Equivalent
SQL0803NDuplicate key23505 (unique_violation)
SQL0530NFK constraint violation23503 (foreign_key_violation)
SQL0545NCheck constraint violation23514 (check_violation)
SQL0911NDeadlock or timeout40P01 (deadlock_detected)
SQL0913NDeadlock rollback40001 (serialization_failure)
SQL0204NObject not found42P01 (undefined_table)
SQL0206NColumn not found42703 (undefined_column)
SQL0100No data found02000 (no_data)
SQL0104NSyntax error42601 (syntax_error)

12. Post-Migration Validation

12.1 Data Integrity Validation

Row Count Verification

-- DB2: Generate row counts
SELECT
TABSCHEMA || '.' || TABNAME AS table_name,
CARD AS row_count
FROM SYSCAT.TABLES
WHERE TABSCHEMA = 'MYSCHEMA'
AND TYPE = 'T'
ORDER BY TABNAME;
-- HeliosDB: Compare row counts
SELECT
schemaname || '.' || relname AS table_name,
n_live_tup AS row_count
FROM pg_stat_user_tables
WHERE schemaname = 'myschema'
ORDER BY relname;

Checksum Validation

-- Sample checksum query
SELECT
COUNT(*) AS row_count,
SUM(CAST(emp_id AS BIGINT)) AS id_sum,
SUM(CAST(salary AS DECIMAL(20,2))) AS salary_sum
FROM employees;

12.2 Functional Validation

Stored Procedure Testing

-- Create test tracking table
CREATE TABLE migration_tests (
test_id SERIAL PRIMARY KEY,
test_name VARCHAR(200),
test_type VARCHAR(50),
db2_result TEXT,
helios_result TEXT,
status VARCHAR(20),
tested_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Test procedure execution
DO $$
DECLARE
v_result TEXT;
BEGIN
CALL my_procedure(123, v_result);
INSERT INTO migration_tests (test_name, test_type, helios_result, status)
VALUES ('my_procedure', 'PROCEDURE', v_result,
CASE WHEN v_result = 'expected' THEN 'PASS' ELSE 'FAIL' END);
END $$;

12.3 Application Validation Checklist

CategoryValidation ItemStatus
ConnectivityAll applications connect successfully[ ]
ConnectivityConnection pooling works[ ]
ConnectivitySSL/TLS encryption enabled[ ]
DataRow counts match[ ]
DataChecksums match[ ]
DataSample data spot checks[ ]
SchemaAll tables created[ ]
SchemaAll indexes created[ ]
SchemaAll constraints active[ ]
SchemaAll sequences created[ ]
ProceduresAll procedures compile[ ]
ProceduresProcedures return correct values[ ]
TriggersTriggers fire correctly[ ]
SecurityUsers created[ ]
SecurityGrants applied[ ]
PerformanceKey queries perform acceptably[ ]
ApplicationCRUD operations work[ ]
ApplicationTransactions commit/rollback[ ]

12.4 Performance Baseline Comparison

-- Capture query execution times
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
SELECT
c.customer_name,
COUNT(o.order_id) AS order_count,
SUM(o.amount) AS total_amount
FROM customers c
JOIN orders o ON c.customer_id = o.customer_id
WHERE o.order_date >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY c.customer_name
ORDER BY total_amount DESC
FETCH FIRST 100 ROWS ONLY;

12.5 Rollback Plan

In case issues are discovered post-migration:

Quick Rollback Steps

  1. Stop application writes to HeliosDB
  2. Redirect connections back to DB2
    Terminal window
    # Update DNS or load balancer to point to DB2
    # Or update db2cli.ini to original DB2 server
  3. Sync any delta data (if dual-write was enabled)
  4. Verify DB2 operations
  5. Investigate and resolve HeliosDB issues
  6. Re-attempt migration when ready

Appendix A: Quick Reference Card

Essential Commands

Terminal window
# Connect via DB2 CLP
db2 connect to heliosdb user admin using password
# Execute query
db2 "SELECT * FROM employees FETCH FIRST 10 ROWS ONLY"
# Check connection status
db2 "SELECT CURRENT SERVER FROM SYSIBM.SYSDUMMY1"

Connection Parameters

ParameterDefaultDescription
Port50000DRDA port
DatabaseheliosdbDatabase name
ProtocolTCPIPConnection protocol

Configuration Files

FileLocationPurpose
db2cli.ini~/sqllib/cfg/CLI configuration
db2dsdriver.cfg~/sqllib/cfg/Data source config
heliosdb.toml/etc/heliosdb/Server configuration

Appendix B: Migration Timeline Template

WeekPhaseActivities
1AssessmentInventory, complexity analysis
2PlanningDesign migration strategy, test plan
3-4Schema MigrationExport DDL, translate, create in HeliosDB
5-6Data MigrationInitial data load, verify
7-8Procedure MigrationConvert SQL PL procedures, functions
9TestingFunctional testing, performance testing
10Parallel RunDual-write, validate
11CutoverSwitch primary to HeliosDB
12StabilizationMonitor, optimize, close out

Related Documentation:


Document History:

  • v1.0 (January 2026): Initial comprehensive guide