Last updated: 2026-06-14

Cross-engine database migration

Cross-engine migration moves tables and data between databases running on different engines — SQL Server to PostgreSQL, MySQL to PostgreSQL, Oracle to PostgreSQL, and other pairs. Unlike a backup/restore (which only works within one engine), the challenge is translating types and values across dialects. Jam SQL Studio does this from the Object Explorer: right-click a table or a whole database, point it at a target connection of any engine, and it generates the translated DDL and copies the rows.

This page is the overview. For a specific pair, jump to its guide: SQL Server → PostgreSQL, MySQL → PostgreSQL, Oracle → PostgreSQL, or SQL Server → MySQL.

How it works: one canonical type model

Every type mapping flows through a single canonical type model. A source type is mapped to an engine-neutral canonical type, and the canonical type is mapped to the closest faithful type on the target. This is the same model that powers cross-engine Schema Compare, so "are these two columns the same?" and "what should this column become?" are answered consistently.

A concrete trace: SQL Server nvarchar(100) → canonical varchar(100) → PostgreSQL character varying(100); MySQL tinyint(1) → canonical boolean → PostgreSQL boolean; Oracle NUMBER(10,0) → canonical int32 → PostgreSQL integer. User-defined alias types (a SQL Server CREATE TYPE dbo.Name FROM nvarchar(50), like AdventureWorks uses) are resolved to their underlying base type first, so they map cleanly instead of being treated as unknown. When a source type has no faithful canonical equivalent (SQL Server sql_variant, spatial types, CLR), Jam emits it verbatim with a warning rather than silently dropping or guessing.

What's mechanical, what's manual

The honest boundary is the same for every pair:

✅ Migrated automatically

  • Tables and columns, with types translated through the canonical model
  • Identity / auto-increment (with the sequence reset after load)
  • DEFAULT, CHECK, and UNIQUE constraints; primary keys
  • Foreign keys with their ON DELETE / ON UPDATE actions (added in a second pass)
  • Indexes, including filtered/partial and covering indexes
  • Computed/generated columns where the expression is portable
  • All row data, with value coercion (booleans, binary, dates, JSON)
  • Schema placement — a table in a non-default source schema is recreated under a matching schema on targets that have them (PostgreSQL, SQL Server); on engines without a separate schema namespace (MySQL, SQLite, Oracle) it lands in the connection's default schema, with a note

✍️ Left as a manual port

  • Views (the query body is dialect-specific)
  • Stored procedures and functions (T-SQL ≠ PL/pgSQL ≠ PL/SQL)
  • Triggers (statement-level vs row-level models differ)
  • Non-portable default expressions (engine-specific functions)
  • Per-column collation
  • Engine-specific features (partitioning schemes, sequences referenced by name)

Jam never claims to translate a procedural body — that's the boundary where a wrong answer is worse than an honest "port this by hand." Instead, a cross-engine Schema Compare gives you the exact list of which views, routines, and triggers exist on the source and not the target, so the manual work is scoped and visible.

Supported migration pairs

Migration is symmetric at the table level — any source to any target among the five engines. These have dedicated guides:

From → ToHeadline type changesGuide
SQL Server → PostgreSQLbitboolean, nvarcharvarchar, uniqueidentifieruuid, datetime2timestampGuide
MySQL → PostgreSQLtinyint(1)boolean, datetimetimestamp, AUTO_INCREMENTIDENTITY, unsigned widensGuide
Oracle → PostgreSQLVARCHAR2varchar, NUMBERnumeric/int, DATEtimestamp, CLOBtextGuide
SQL Server → MySQLbittinyint(1), uniqueidentifierchar(36), datetime2datetime, IDENTITYAUTO_INCREMENTGuide
Any other pairSame canonical model; types map through the neutral layerRight-click → Migrate

The migration workflow

  1. Connect both databases. Add the source and target connections; both appear in the Object Explorer. (See Connections.)
  2. Right-click → Migrate Table to Connection… (or right-click the database for Migrate all tables to connection…, where Choose tables… lets you migrate every table or a searched subset). This opens a dedicated migration tab — a migration can be long-running, so it gets its own workspace surface rather than a modal dialog.
  3. Preview. A dry run shows the translated CREATE TABLE + INSERT script in the target dialect, the exact number of rows it will copy, and any warnings — without touching the target. To stay readable for huge tables, the script lists at most a 50-row sample of INSERTs with a banner noting that the migration copies the full table chunk by chunk (a 2-million-row source previews instantly; the preview never materializes more than 50 rows). The preview also reports its progress live (analyzing the table, counting rows, building the script) instead of a blank spinner.
  4. Migrate. Confirm, and the tab streams the copy live: the current table and phase (creating schema → copying data), an overall progress bar, and rows-copied of the total. Data is read and inserted in chunks, so a large table never loads entirely into memory. Row counts are re-checked on both sides afterward.
  5. Cancel anytime. Cancel migration stops at the next chunk boundary; if a table was only partially copied, you're asked whether to drop the partial table(s) or keep what was copied so far.
  6. Verify. Use Verify with Data Compare to confirm values, not just counts.
  7. Finish the schema. Run a cross-engine Schema Compare for the object inventory, then port the procedural objects by hand.

Frequently asked questions

What is cross-engine database migration?

Cross-engine migration copies tables and data between databases that run on different engines — for example SQL Server to PostgreSQL, MySQL to PostgreSQL, or Oracle to PostgreSQL. It differs from a backup/restore or a dump/load, which only work within the same engine. The hard part is translating types and values between dialects, which Jam SQL Studio does through a canonical type model: each source type maps to an engine-neutral type, then to the closest faithful target type.

Which database engines can Jam SQL Studio migrate between?

Any pair among SQL Server, PostgreSQL, MySQL/MariaDB, Oracle, and SQLite. The most common direction is consolidating onto PostgreSQL (from SQL Server, MySQL, or Oracle), but the engine is symmetric — it works for any source/target combination at the table level.

Does cross-engine migration move stored procedures and triggers?

No. Cross-engine migration moves table shape and data — columns, types, identity, defaults, constraints, foreign keys, indexes, and rows. Procedural code (stored procedures, functions, triggers, views) is written in each engine's dialect and does not translate 1:1, so Jam leaves it as a manual port and gives you a by-name inventory of what's missing rather than emitting a guess.