---
title: "Konwersja MySQL do PostgreSQL"
description: "Konwertuj zrzut MySQL lub MariaDB na skrypt PostgreSQL, który ładuje się za pierwszym razem, z raportem każdej zmiany. W przeglądarce, bez wysyłania zrzutu."
canonical: https://intosql.com/pl/mysql-do-postgresql
last_updated: 2026-10-15
---

# Konwersja MySQL do PostgreSQL

Upuść zrzut z mysqldump, mariadb-dump, mysqlpump, phpMyAdmin lub Adminer jako .sql lub .sql.gz i pobierz skrypt PostgreSQL z tymi samymi tabelami, kluczami, indeksami i danymi. Każda wartość, której PostgreSQL nie może przechować bez zmian, i każdy obiekt, którego nie przenosi, są wymienione w raporcie.

## Co zmienia się między MySQL a PostgreSQL

Każdy wiersz to reguła stosowana przez konwerter, z wpisem, który dodaje do raportu, gdy reguła coś zmienia w twoich danych.

| W MySQL | W PostgreSQL | Wpis w raporcie |
| --- | --- | --- |
| TINYINT(1), BOOL | boolean, gdy każda wartość to 0 lub 1, w przeciwnym razie smallint | `bool_kept_numeric` |
| UNSIGNED integers | następny szerszy typ całkowity z CHECK, że wartość nie jest ujemna; BIGINT UNSIGNED to bigint, gdy każda wartość się mieści, w przeciwnym razie numeric(20,0) | `unsigned_widened` |
| ZEROFILL and display widths | usunięte | `zerofill_dropped` |
| FLOAT(M,D) | real lub double precision, bez skali | `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 usunięte | `not_null_relaxed` |
| DEFAULT '0000-00-00' | brak wartości domyślnej | `zero_date_default` |
| TIME | time, gdy każda wartość mieści się w dobie, w przeciwnym razie interval | `time_as_interval` |
| YEAR | smallint z CHECK zakresu |  |
| CHAR(n) | varchar(n) |  |
| DATETIME | timestamp |  |
| TIMESTAMP | timestamptz w strefie czasowej podanej w zrzucie, UTC, gdy jej nie podaje | `timestamp_zone_assumed` |
| ENUM | text z CHECK dozwolonych wartości |  |
| ENUM holding '' (MySQL's error value) | pusta wartość dopuszczona przez CHECK | `enum_invalid_value` |
| ENUM or SET holding values outside its list | bez CHECK | `enum_check_skipped` |
| SET | text[] z CHECK, że każdy element jest na liście |  |
| JSON | jsonb; json, gdy wartość zawiera \u0000 | `json_not_jsonb` |
| NUL bytes in text | usunięte | `nul_removed` |
| text that isn't valid in its character set | błędne bajty jako znak zastępczy | `invalid_utf8_replaced` |
| text decoded twice (Ã±) | skopiowane bez zmian | `mojibake_suspected` |
| AUTO_INCREMENT | GENERATED BY DEFAULT AS IDENTITY, z licznikiem ustawionym za skopiowanymi id |  |
| MyISAM AUTO_INCREMENT on the second column of a key | jeden licznik dla tabeli | `myisam_group_autoincrement` |
| ON UPDATE CURRENT_TIMESTAMP | wyzwalacz BEFORE UPDATE | `on_update_trigger` |
| generated columns | STORED | `virtual_as_stored` |
| generated columns with functions PostgreSQL lacks | zwykła kolumna | `generated_not_translated` |
| INVISIBLE columns | zwykłe kolumny | `invisible_column` |
| CHECK constraints | przetłumaczone, wewnątrz CREATE TABLE |  |
| CHECK constraints with functions PostgreSQL lacks | nie jest tworzone | `check_skipped` |
| CHECK ... NOT ENFORCED | nie jest tworzone | `check_not_enforced` |
| defaults with functions PostgreSQL lacks | brak wartości domyślnej | `default_not_translated` |
| keys and indexes on a prefix, c(20) | indeks na left(c, 20) | `prefix_unique` |
| FULLTEXT indexes | GIN na to_tsvector('simple', ...) | `fulltext_as_gin` |
| indexes on values over 2,000 bytes | hash | `index_on_wide_values` |
| SPATIAL indexes | nie jest tworzony bez PostGIS | `spatial_index_skipped` |
| functional indexes PostgreSQL can't write | nie jest tworzony | `index_skipped` |
| foreign keys | po danych, jako NOT VALID, potem sprawdzany z ostrzeżeniem o osieroconych wierszach |  |
| foreign keys to columns without a unique key | nie jest tworzony | `foreign_key_skipped` |
| table and column names | małe litery, gdy nazwy pozostają unikalne | `identifier_renamed` |
| names over 63 bytes | skrócone z hashem | `name_shortened` |
| GEOMETRY, POINT, POLYGON... | WKB w bytea | `geometry_as_wkb` |
| INET4, INET6, UUID (MariaDB) | inet, uuid |  |
| BINARY, VARBINARY, BLOB | bytea |  |
| PARTITION BY | jedna tabela | `partitions_dropped` |
| WITH SYSTEM VERSIONING (MariaDB) | tabela z bieżącymi wierszami | `system_versioning_dropped` |
| MyISAM, MEMORY and other engines | zwykła tabela | `engine_dropped` |
| views, triggers, procedures, functions and events | wymienione w raporcie | `not_converted_objects` |
| dumps without CREATE TABLE | typy odczytane z wartości | `no_schema` |
| geometries in a dump without CREATE TABLE | WKB w bytea | `geometry_inferred` |
| _ci collations | dokładne porównanie | `case_insensitive_collation` |
| SET NAMES utf8 from utf8mb4 tables | przekonwertowane, z ostrzeżeniem | `dump_lost_four_byte_chars` |
| dumps without SET NAMES whose text isn't UTF-8 | odczytane jako Latin-1 (Windows-1252) | `charset_guessed` |
| sjis, cp932, gbk, big5 dumps | odczytane jako UTF-8, z ostrzeżeniem | `unsupported_charset` |
| UNHEX('..'), CONVERT(b'..', UNSIGNED), CONVERT(".." USING x), ST_GeomFromText('..') in rows | obliczone |  |
| other expressions in rows | NULL | `expression_value` |
| DEFAULT in VALUES | wartość domyślna kolumny | `default_keyword_filled` |
| DEFAULT in VALUES without a literal default | NULL | `default_keyword_null` |
| REPLACE and INSERT IGNORE | zwykłe wiersze | `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 z bieżącą wartością |  |

## Załaduj skrypt do PostgreSQL

Skrypt tworzy tabele, kopiuje wiersze, a potem dodaje klucze, indeksy i klucze obce, więc ładuje się szybko i zatrzymuje przy pierwszym błędzie.

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

Klucze obce są dodawane jako NOT VALID, a potem sprawdzane. Jeśli wiersz wskazuje na nieistniejący wiersz, skrypt podaje, którego ograniczenia to dotyczy, zamiast przerwać w połowie.

Przy dużym zrzucie najpierw utwórz bazę danych i uruchom skrypt przez psql na tej samej maszynie co serwer.

## Jak zrobić zrzut MySQL dla najlepszego wyniku

Konwerter odczytuje to, co zawiera zrzut. Te opcje zachowują w nim więcej twoich danych:

- --default-character-set=utf8mb4 zachowuje emoji i inne 4-bajtowe znaki, które zrzut utf8 traci, zanim zobaczy go konwerter.
- --hex-blob zapisuje kolumny binarne szesnastkowo, co przetrwa kopiowanie między systemami.
- --routines --triggers --events dodają te obiekty do zrzutu, aby raport mógł je wymienić.

## Co nie jest konwertowane

Widoki, wyzwalacze, procedury składowane, funkcje i zdarzenia są pisane we własnym języku każdej bazy danych. Raport wymienia je z nazwy i nigdy nie pomija ich po cichu, więc możesz je przepisać dla PostgreSQL.

## Porównanie z pgloader

Te same zrzuty, przekonwertowane i załadowane przez IntoSQL i przez pgloader 3.6.7 na jednej maszynie (10-rdzeniowy i9-10900K z SATA SSD), w październiku 2026.

- Kolumna TINYINT(1) z wartościami 2, -1 i -5: pgloader ładuje dla każdej true, bez ostrzeżenia. IntoSQL zachowuje liczby, a raport wyjaśnia dlaczego.
- Zrzut z wartością domyślną 'it's', tabelą z grawisem w nazwie, ENUM z pustą wartością i TIME powyżej 24 godzin: pgloader się zatrzymuje. IntoSQL go konwertuje i ładuje.
- To, co ładuje pgloader, traci klucze główne, unikalne i obce oraz kolumny identity. IntoSQL zachowuje każdy z nich.
- Zrzut 5.3 GB z 30 milionami wierszy: pgloader wymaga najpierw odtworzenia go w działającym MySQL, co zajmuje 18 minut, a potem przy ustawieniach domyślnych brakuje mu pamięci. IntoSQL konwertuje zrzut w 10 sekund, a psql ładuje skrypt w około 3 minuty.
- W 476 zrzutach z MySQL od 5.5 do 9 i MariaDB od 10.3 do 12, załadowanych do PostgreSQL 13 i 18: bez błędów ładowania, a żadna wartość nie zmieniła się bez wpisu w raporcie.

## Pytania o konwersję MySQL do PostgreSQL

### Czy mój zrzut jest wysyłany?

Nie. Konwerter działa w przeglądarce i odczytuje zrzut z dysku po kawałku, więc nigdy nie opuszcza on twojego komputera. Aplikacja na komputer i wiersz poleceń też konwertują na twoim komputerze.

### Jak duży może być zrzut?

Konwerter nigdy nie trzyma całego zrzutu w pamięci: czyta plik dwa razy, fragmentami, i zapisuje skrypt na bieżąco. Zrzuty wielogigabajtowe konwertują się w przeglądarce, w aplikacji na komputer i w wierszu poleceń.

### Czy odczytuje zrzuty MariaDB?

Tak. Zrzuty z mariadb-dump i z MariaDB od 10.3 do 12 są konwertowane tak samo, łącznie z kolumnami INET6, INET4 i UUID z MariaDB.

### Co dzieje się z datami 0000-00-00?

PostgreSQL nie ma daty zerowej, więc stają się NULL, a kolumna przyjmuje NULL. Raport podaje, ile ich było w każdej kolumnie.

### Czy wartości AUTO_INCREMENT są zachowywane?

Tak. Każda kolumna AUTO_INCREMENT staje się kolumną identity, każdy wiersz zachowuje swoje id, a kolejne id idzie po najwyższym albo po AUTO_INCREMENT tabeli, jeśli ten jest wyższy.

### Czy TINYINT(1) staje się boolean?

Tylko gdy każda wartość w kolumnie to 0 lub 1. Jeśli zawiera inne liczby, np. 2 lub -1, pozostaje liczbą, a raport wyjaśnia dlaczego, więc żadna wartość nie zmieni się przypadkiem w true.

### A procedury składowane i wyzwalacze?

Raport wymienia je z nazwy, ale nie są konwertowane, bo każda baza danych zapisuje je we własnym języku. Wyjątkiem jest ON UPDATE CURRENT_TIMESTAMP: staje się wyzwalaczem PostgreSQL.

### Na jakich wersjach PostgreSQL ładuje się skrypt?

PostgreSQL od 13 do 18. Ten sam skrypt ładuje się na każdej z nich i zatrzymuje przy pierwszym błędzie, jeśli coś pójdzie nie tak.

## Inne konwersje do PostgreSQL

- [Konwersja Excel do PostgreSQL](https://intosql.com/pl/excel-do-postgresql)
- [Konwersja CSV do PostgreSQL](https://intosql.com/pl/csv-do-postgresql)
- [Konwersja JSON do PostgreSQL](https://intosql.com/pl/json-do-postgresql)
