MySQL to PostgreSQL Converter

Paste MySQL DDL or a dump, get PostgreSQL DDL plus a manual-fix checklist. Free and private.

At a glance

MySQL to PostgreSQL Converter is a free, client-side tool that translates MySQL DDL and dump statements into PostgreSQL DDL. It maps types (TINYINT(1) to BOOLEAN, UNSIGNED widening, DATETIME to TIMESTAMP), rewrites AUTO_INCREMENT, indexes, and INSERT patterns, and flags what needs manual work. Nothing is uploaded and no account is required.

Universal Switcher:
From:
To:

100% Client-Side Migration Blueprint

Your schema is converted strictly in local browser memory. Zero uploads, zero servers, zero sign-up.

Samples:

How do I convert MySQL to PostgreSQL?

Paste MySQL DDL or a mysqldump excerpt into the converter above and press Convert to PostgreSQL. The tool rewrites CREATE TABLE statements, translates types and INSERT patterns, strips MySQL-only boilerplate, and returns a PostgreSQL starter script plus a checklist of everything it deliberately did not guess. Nothing is uploaded: the conversion runs entirely in your browser, and the result is ready to review on a staging database.

What MySQL types have no direct PostgreSQL equivalent?

PostgreSQL has no UNSIGNED integers, no MEDIUMINT, and no inline ENUM or SET in CREATE TABLE. A mysqldump is the MySQL text export of schema and data that most migrations start from. This table is the exact type rule set the converter applies; every substitution is also reported as a note in the output.

MySQL to PostgreSQL type mapping rules applied by the converter
MySQL type PostgreSQL result Status
INT UNSIGNEDBIGINT (widened)Automatic with note
BIGINT UNSIGNEDNUMERIC(20,0)Automatic with note
TINYINT(1)BOOLEANAutomatic
TINYINT(n) / SMALLINTSMALLINT (UNSIGNED widened to INTEGER)Automatic with note
MEDIUMINTINTEGERAutomatic with note
DECIMAL(p,s) / NUMERICNUMERIC(p,s)Automatic
ENUM('a','b')TEXT + CHECK (col IN (...))Automatic with note
SET('a','b')TEXT placeholder (TEXT[], CHECK, or join table)Manual gap
DATETIMETIMESTAMPAutomatic
TIMESTAMP / TIMETIMESTAMP / TIMEReview (timezone, durations)
TINYTEXT / MEDIUMTEXT / LONGTEXTTEXTAutomatic with note
BLOB / BINARY / VARBINARYBYTEAAutomatic with note
JSONJSONBAutomatic with note
YEARSMALLINTAutomatic with note
AUTO_INCREMENTGENERATED BY DEFAULT AS IDENTITYAutomatic
GEOMETRY / POINT / SPATIALPostGIS (rebuild by hand)Manual gap

Which MySQL statements convert automatically in a dump?

The converter works statement by statement, so pasting a full mysqldump excerpt is fine. These are the exact rewrite rules applied; anything else is carried over as a comment for manual review.

MySQL statement to PostgreSQL conversion rules applied by the converter
MySQL statement or pattern PostgreSQL result Status
`backtick` identifiers"double-quoted" identifiersAutomatic
# comment-- commentAutomatic
LIMIT offset,countLIMIT count OFFSET offsetAutomatic
INSERT IGNORE INTOINSERT ... ON CONFLICT DO NOTHINGAutomatic
ON DUPLICATE KEY UPDATEON CONFLICT (pk) DO UPDATE SET col = EXCLUDED.colAutomatic when the primary key is in the pasted input
UNIQUE KEY name (col)CONSTRAINT "name" UNIQUE ("col")Automatic
KEY name (col)CREATE INDEX "name" ON table ("col")Automatic
/*!40101 ... */ conditionalsRemoved (mysqldump boilerplate)Removed with note
SET NAMES / SQL_MODE / time_zoneRemovedRemoved with note
LOCK TABLES / UNLOCK TABLESRemovedRemoved with note
USE db / CREATE DATABASERemoved (PostgreSQL connects per database)Removed with note
ENGINE / CHARSET / COLLATE / ROW_FORMAT optionsRemoved from the CREATE TABLE tailRemoved with note
REPLACE INTOCommented out for manual rewriteManual gap
UPDATE / DELETE ... LIMITCommented out for manual rewriteManual gap
Stored procedures / functions / triggers / eventsCommented out; rewrite in PL/pgSQLManual gap

What must be fixed by hand after the conversion?

These constructs have no safe automatic mapping. The converter flags each one it finds in your input with its exact location, and the same items are collected in the migration effort estimate.

  • FULLTEXT indexes → rebuild with tsvector + GIN or pg_trgm
  • SPATIAL / geometry columns → PostGIS extension and indexes
  • PARTITION BY → rewrite as PostgreSQL declarative partitioning
  • Stored routines, triggers, events → rewrite in PL/pgSQL
  • col(n) prefix indexes → substring expression index
  • SET columns → TEXT[], TEXT + CHECK, or a join table
  • REPLACE INTO → ON CONFLICT DO UPDATE or DELETE + INSERT
  • ON DUPLICATE KEY UPDATE without a known PK → pick the conflict target
  • UPDATE/DELETE ... LIMIT → ctid or key subquery
  • ON UPDATE CURRENT_TIMESTAMP → trigger or application logic
  • VIRTUAL generated columns → mapped to STORED, verify behavior
  • Double-quoted strings in MySQL mode → verify literal vs identifier

How is the migration effort estimate calculated?

The tool counts the converted items and the flagged manual gaps, then applies the fixed published weights below. The result is a t-shirt size with an itemized breakdown: S under 15 points, M 15–40 points, L above 40 points. It is a planning aid for scoping the migration, not a quote.

Base: table 3 · column 0.5 · index 1 · insert 0.2

Manual gaps: routine 8 · fulltext 8 · spatial 8 · partition 8 · prefix index 5

Manual gaps: set column 3 · replace into 3

Manual gaps: update/delete limit 2 · on-duplicate unknown target 2 · on update timestamp 2 · virtual generated 2

MySQL vs PostgreSQL function equivalents

Function calls inside SELECT, WHERE, and other DML are not rewritten automatically (that would require evaluating your queries); use this table when you review converted data statements. DDL statements are rewritten for you; function bodies are not.

Common MySQL function equivalents in PostgreSQL
MySQL PostgreSQL equivalent
IFNULL(a, b)COALESCE(a, b)
NOW() / CURDATE()now() / CURRENT_DATE
DATE_FORMAT(d, '%Y-%m-%d')TO_CHAR(d, 'YYYY-MM-DD')
STR_TO_DATE(s, fmt)TO_DATE / TO_TIMESTAMP(s, fmt)
GROUP_CONCAT(x SEPARATOR ',')STRING_AGG(x, ',')
CONCAT(a, b)CONCAT(a, b) or a || b
LOCATE(s, str)STRPOS(str, s)
UNIX_TIMESTAMP()EXTRACT(EPOCH FROM now())
FROM_UNIXTIME(ts)TO_TIMESTAMP(ts)
RAND()random()

Why Use This MySQL to PostgreSQL Converter?

Deterministic type mapping: TINYINT(1) to BOOLEAN, UNSIGNED widening, MEDIUMINT to INTEGER, DATETIME to TIMESTAMP, text/blob families to TEXT/BYTEA, JSON to JSONB, ENUM to TEXT + CHECK, AUTO_INCREMENT to identity columns.
Statement rewrites for real dumps: backticks to double quotes, LIMIT offset,count to LIMIT count OFFSET offset, INSERT IGNORE to ON CONFLICT DO NOTHING, and ON DUPLICATE KEY UPDATE to ON CONFLICT DO UPDATE when the primary key is in the pasted input.
Manual-gap checklist with reasons: FULLTEXT and spatial indexes, prefix indexes, partitioning, SET columns, stored routines, ON UPDATE CURRENT_TIMESTAMP, and VIRTUAL generated columns.
Fixed-weight S/M/L effort estimate (table 3, column 0.5, index 1, insert 0.2, plus documented gap weights) with an itemized breakdown.
Static type, statement, and function mapping tables work with JavaScript disabled. Copy or download the generated PostgreSQL script. 100% client-side, no signup.

How to Use MySQL to PostgreSQL Converter

1

Paste MySQL DDL or a dump

Paste CREATE TABLE statements or a mysqldump excerpt (schema or schema+data) into the input box, or load the sample.

2

Review the PostgreSQL script and checklist

The tool converts statements, lists every type mapping applied, and flags constructs that need manual work with a reason.

3

Plan with the effort estimate

Use the S/M/L estimate and gap list to scope the remaining manual work before running the script on a staging database.

Worked example: users table with auto-increment and a named unique key

The engine splits the statement in browser memory, widens INT UNSIGNED to BIGINT, rewrites AUTO_INCREMENT as an identity column, maps TINYINT(1) to BOOLEAN and DATETIME to TIMESTAMP, keeps the primary key, turns the named unique key into a UNIQUE constraint, and strips the ENGINE/charset table options with conversion notes; this table has no manual gaps. The input/output pair above matches the engine output.

MySQL input (users table) Source
CREATE TABLE `users` (
  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `email` varchar(255) NOT NULL,
  `active` tinyint(1) NOT NULL DEFAULT '1',
  `created_at` datetime DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
PostgreSQL output (starter script) Processed
CREATE TABLE "users" (
  "id" BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL,
  "email" VARCHAR(255) NOT NULL,
  "active" BOOLEAN NOT NULL DEFAULT true,
  "created_at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY ("id"),
  CONSTRAINT "uq_email" UNIQUE ("email")
);

Technical Specifications & Engine Details

Technical specifications and engine details for MySQL to PostgreSQL Converter
Specification Details
Supported Formats MYSQL-DDL, MYSQL-DUMP, SQL-TEXT → POSTGRESQL-DDL, POSTGRESQL-SQL, CHECKLIST, ESTIMATE
Execution Mode 100% Client-Side In-Browser (client)
Browser Requirements Modern browser with JavaScript and HTML5 APIs enabled.
Performance Constraints Text-in/text-out converter; no database connection and no execution. Stored procedures, triggers, events, and function bodies are flagged as manual, not rewritten. Complex constructs (partitioning, spatial data) are documented gaps. Output is a reviewed starter migration script, verify before running.
Maintained by Pragyan Pahadi

100% Client-Side Privacy Guarantee

Pasted MySQL schemas and dumps are converted 100% locally in your browser memory. No schema content, data, or credentials embedded in the input are ever sent to any server.

Frequently Asked Questions

Can I convert a MySQL dump to PostgreSQL automatically?
Yes for schema and simple data statements. Paste mysqldump output and the tool rewrites CREATE TABLE statements, strips MySQL-only boilerplate, and translates INSERT patterns such as INSERT IGNORE into ON CONFLICT DO NOTHING. Stored procedures, triggers, and MySQL-specific options are listed in the checklist for manual review.
What MySQL types have no direct PostgreSQL equivalent?
PostgreSQL has no UNSIGNED integers, no MEDIUMINT, no SET type, and no inline ENUM in CREATE TABLE. The tool applies deterministic substitutes (widen UNSIGNED to the next larger signed type, MEDIUMINT to INTEGER, ENUM to TEXT with a CHECK constraint) and records every substitution as a note you can review.
Does the converter send my schema to a server?
No. All parsing and conversion run 100% client-side in your browser memory. Your schema, dump text, and any credentials embedded in it are never uploaded, stored, or transmitted.
How is the migration effort estimate calculated?
The tool counts tables, columns, indexes, and flagged manual-gap items, then applies fixed published weights to produce a t-shirt size (S/M/L) with an itemized breakdown. It is a planning aid for scoping work, not a quote or guarantee.

Methodology

Conversion rules map MySQL types and table options to PostgreSQL equivalents. Review the generated DDL against your schema before running it.

Last updated .