---
title: "Convertir MySQL en PostgreSQL"
description: "Convertissez un dump MySQL ou MariaDB en script PostgreSQL qui se charge du premier coup, avec un rapport de chaque changement. Dans le navigateur, sans envoi."
canonical: https://intosql.com/fr/mysql-en-postgresql
last_updated: 2026-10-15
---

# Convertir MySQL en PostgreSQL

Déposez un dump de mysqldump, mariadb-dump, mysqlpump, phpMyAdmin ou Adminer, en .sql ou .sql.gz, et téléchargez un script PostgreSQL avec les mêmes tables, clés, index et données. Chaque valeur que PostgreSQL ne peut pas contenir telle quelle, et chaque objet qu'il ne reprend pas, est listé dans le rapport.

## Ce qui change de MySQL à PostgreSQL

Chaque ligne est une règle appliquée par le convertisseur, avec la ligne de rapport qu'il écrit quand la règle change quelque chose dans vos données.

| Dans MySQL | Dans PostgreSQL | Ligne du rapport |
| --- | --- | --- |
| TINYINT(1), BOOL | boolean si chaque valeur vaut 0 ou 1, sinon smallint | `bool_kept_numeric` |
| UNSIGNED integers | l'entier immédiatement plus large, avec un CHECK qui interdit les négatifs ; BIGINT UNSIGNED devient bigint si chaque valeur y tient, sinon numeric(20,0) | `unsigned_widened` |
| ZEROFILL and display widths | supprimé | `zerofill_dropped` |
| FLOAT(M,D) | real ou double precision, sans l'échelle | `float_scale_dropped` |
| BIT(1), BIT(n) | boolean, bit(n) |  |
| zero, partial or impossible dates (0000-00-00, 2024-02-30) | NULL | `invalid_date_null` |
| NOT NULL columns with values that become NULL | NOT NULL retiré | `not_null_relaxed` |
| DEFAULT '0000-00-00' | aucune valeur par défaut | `zero_date_default` |
| TIME | time si chaque valeur tient dans une journée, sinon interval | `time_as_interval` |
| YEAR | smallint avec un CHECK de sa plage |  |
| CHAR(n) | varchar(n) |  |
| DATETIME | timestamp |  |
| TIMESTAMP | timestamptz dans le fuseau horaire indiqué par le dump, UTC s'il n'en indique aucun | `timestamp_zone_assumed` |
| ENUM | text avec un CHECK de ses valeurs |  |
| ENUM holding '' (MySQL's error value) | la valeur vide autorisée par le CHECK | `enum_invalid_value` |
| ENUM or SET holding values outside its list | pas de CHECK | `enum_check_skipped` |
| SET | text[] avec un CHECK qui vérifie que chaque élément est dans la liste |  |
| JSON | jsonb ; json quand une valeur contient \u0000 | `json_not_jsonb` |
| NUL bytes in text | retiré | `nul_removed` |
| text that isn't valid in its character set | les octets invalides deviennent le caractère de remplacement | `invalid_utf8_replaced` |
| text decoded twice (Ã±) | copié tel quel | `mojibake_suspected` |
| AUTO_INCREMENT | GENERATED BY DEFAULT AS IDENTITY, avec le compteur placé après les identifiants copiés |  |
| MyISAM AUTO_INCREMENT on the second column of a key | un seul compteur pour la table | `myisam_group_autoincrement` |
| ON UPDATE CURRENT_TIMESTAMP | un déclencheur BEFORE UPDATE | `on_update_trigger` |
| generated columns | STORED | `virtual_as_stored` |
| generated columns with functions PostgreSQL lacks | une colonne simple | `generated_not_translated` |
| INVISIBLE columns | colonnes ordinaires | `invisible_column` |
| CHECK constraints | traduites, en ligne dans CREATE TABLE |  |
| CHECK constraints with functions PostgreSQL lacks | non créée | `check_skipped` |
| CHECK ... NOT ENFORCED | non créée | `check_not_enforced` |
| defaults with functions PostgreSQL lacks | aucune valeur par défaut | `default_not_translated` |
| keys and indexes on a prefix, c(20) | un index sur left(c, 20) | `prefix_unique` |
| FULLTEXT indexes | GIN sur to_tsvector('simple', ...) | `fulltext_as_gin` |
| indexes on values over 2,000 bytes | hash | `index_on_wide_values` |
| SPATIAL indexes | non créé sans PostGIS | `spatial_index_skipped` |
| functional indexes PostgreSQL can't write | non créé | `index_skipped` |
| foreign keys | après les données, NOT VALID, puis validée avec un avertissement sur les orphelins |  |
| foreign keys to columns without a unique key | non créée | `foreign_key_skipped` |
| table and column names | en minuscules si le nom reste unique | `identifier_renamed` |
| names over 63 bytes | raccourci avec un hachage | `name_shortened` |
| GEOMETRY, POINT, POLYGON... | WKB dans bytea | `geometry_as_wkb` |
| INET4, INET6, UUID (MariaDB) | inet, uuid |  |
| BINARY, VARBINARY, BLOB | bytea |  |
| PARTITION BY | une seule table | `partitions_dropped` |
| WITH SYSTEM VERSIONING (MariaDB) | une table avec les lignes actuelles | `system_versioning_dropped` |
| MyISAM, MEMORY and other engines | une table ordinaire | `engine_dropped` |
| views, triggers, procedures, functions and events | listés dans le rapport | `not_converted_objects` |
| dumps without CREATE TABLE | types déduits des valeurs | `no_schema` |
| geometries in a dump without CREATE TABLE | WKB dans bytea | `geometry_inferred` |
| _ci collations | comparaison exacte | `case_insensitive_collation` |
| SET NAMES utf8 from utf8mb4 tables | converti, avec un avertissement | `dump_lost_four_byte_chars` |
| dumps without SET NAMES whose text isn't UTF-8 | lu comme Latin-1 (Windows-1252) | `charset_guessed` |
| sjis, cp932, gbk, big5 dumps | lu comme UTF-8, avec un avertissement | `unsupported_charset` |
| UNHEX('..'), CONVERT(b'..', UNSIGNED), CONVERT(".." USING x), ST_GeomFromText('..') in rows | évaluées |  |
| other expressions in rows | NULL | `expression_value` |
| DEFAULT in VALUES | la valeur par défaut de la colonne | `default_keyword_filled` |
| DEFAULT in VALUES without a literal default | NULL | `default_keyword_null` |
| REPLACE and INSERT IGNORE | lignes simples | `replace_as_insert` |
| types IntoSQL doesn't know | text | `unknown_type` |
| values that don't fit their column | NULL | `invalid_value_null` |
| unreadable geometries | NULL | `bad_geometry` |
| CREATE SEQUENCE (MariaDB) | CREATE SEQUENCE avec sa valeur actuelle |  |

## Charger le script dans PostgreSQL

Le script crée les tables, copie les lignes, puis ajoute les clés, les index et les clés étrangères ; il se charge donc vite et s'arrête à la première erreur.

```shell
psql -v ON_ERROR_STOP=1 -d mydb -f mysql.postgresql.sql
```

Les clés étrangères sont ajoutées en NOT VALID, puis validées. Si une ligne pointe vers une ligne qui n'existe pas, le script vous indique quelle contrainte, au lieu d'échouer à mi-chemin.

Pour un gros dump, créez d'abord la base de données et exécutez le script avec psql depuis la machine du serveur.

## Faire le dump MySQL pour un meilleur résultat

Le convertisseur lit ce que contient le dump. Ces options y gardent davantage de vos données :

- --default-character-set=utf8mb4 garde les emoji et autres caractères sur 4 octets, qu'un dump utf8 perd avant que le convertisseur ne le voie.
- --hex-blob écrit les colonnes binaires en hexadécimal, ce qui résiste aux copies entre systèmes.
- --routines --triggers --events ajoutent ces objets au dump, pour que le rapport puisse les lister.

## Ce qui n'est pas converti

Les vues, déclencheurs, procédures stockées, fonctions et événements sont écrits dans le langage propre à chaque base de données. Ils sont listés par nom dans le rapport, jamais supprimés en silence, pour que vous puissiez les réécrire pour PostgreSQL.

## Comparé à pgloader

Les mêmes dumps, convertis et chargés par IntoSQL et par pgloader 3.6.7 sur une même machine (un i9-10900K à 10 cœurs avec un SATA SSD), en octobre 2026.

- Une colonne TINYINT(1) contenant 2, -1 et -5 : pgloader charge true pour chacune, sans avertissement. IntoSQL garde les nombres et le rapport explique pourquoi.
- Un dump avec une valeur par défaut 'it's', une table dont le nom contient un accent grave, un ENUM contenant la valeur vide et un TIME de plus de 24 heures : pgloader s'arrête. IntoSQL le convertit et le charge.
- Ce que pgloader charge a perdu ses clés primaires, uniques et étrangères, et ses identités. IntoSQL les garde toutes.
- Un dump de 5.3 GB et 30 millions de lignes : pgloader exige qu'il soit d'abord restauré dans un MySQL en marche, ce qui prend 18 minutes, puis manque de mémoire avec ses réglages par défaut. IntoSQL convertit le dump en 10 secondes, et psql charge le script en 3 minutes environ.
- Sur 476 dumps de MySQL 5.5 à 9 et de MariaDB 10.3 à 12, chargés dans PostgreSQL 13 et 18 : aucune erreur de chargement, et aucune valeur modifiée sans une ligne dans le rapport.

## Questions sur MySQL vers PostgreSQL

### Mon dump est-il envoyé ?

Non. Le convertisseur s'exécute dans votre navigateur et lit le dump depuis votre disque par morceaux ; il ne quitte donc jamais votre ordinateur. L'application de bureau et la ligne de commande convertissent aussi sur votre ordinateur.

### Quelle taille peut avoir le dump ?

Le convertisseur ne garde jamais tout le dump en mémoire : il lit le fichier deux fois, par plages, et écrit le script au fur et à mesure. Les dumps de plusieurs gigaoctets se convertissent dans le navigateur, dans l'application de bureau et avec la ligne de commande.

### Lit-il les dumps MariaDB ?

Oui. Les dumps de mariadb-dump et de MariaDB 10.3 à 12 se convertissent de la même façon, y compris les colonnes INET6, INET4 et UUID de MariaDB.

### Que deviennent les dates 0000-00-00 ?

PostgreSQL n'a pas de date zéro ; elles deviennent donc NULL et la colonne accepte NULL. Le rapport indique combien il y en avait dans chaque colonne.

### Les valeurs AUTO_INCREMENT sont-elles conservées ?

Oui. Chaque colonne AUTO_INCREMENT devient une colonne d'identité, chaque ligne garde son identifiant, et le prochain identifiant reprend après le plus élevé, ou après l'AUTO_INCREMENT de la table s'il est plus grand.

### TINYINT(1) devient-il boolean ?

Seulement si chaque valeur de la colonne vaut 0 ou 1. Si elle contient d'autres nombres, comme 2 ou -1, elle reste un nombre et le rapport explique pourquoi ; aucune valeur ne devient true par accident.

### Et les procédures stockées et les déclencheurs ?

Ils sont listés par nom dans le rapport et ne sont pas convertis, car chaque base de données les écrit dans son propre langage. ON UPDATE CURRENT_TIMESTAMP est l'exception : il devient un déclencheur PostgreSQL.

### Sur quelles versions de PostgreSQL le script se charge-t-il ?

PostgreSQL 13 à 18. Le même script se charge sur chacune, et s'arrête à la première erreur en cas de problème.

## Autres conversions vers PostgreSQL

- [Convertir Excel en PostgreSQL](https://intosql.com/fr/excel-en-postgresql)
- [Convertir CSV en PostgreSQL](https://intosql.com/fr/csv-en-postgresql)
- [Convertir JSON en PostgreSQL](https://intosql.com/fr/json-en-postgresql)
