Przejdź do treści
Strona główna IntoSQL

Konwertuj bazę danych na inną bazę danych

Upuść zrzut z mysqldump, mariadb-dump, pg_dump, SSMS, SQL Developer lub SQLcl albo plik .db SQLite i pobierz jeden skrypt dla PostgreSQL, MySQL, MariaDB, SQLite, SQL Server lub Oracle z tymi samymi tabelami, kluczami, indeksami i danymi. Każda zmiana jest wymieniona w raporcie, a zrzut nigdy nie opuszcza twojego komputera.

Twój plik
sqlshop_2024.sqlPlik przykładowy, 5,1 kB
Twoja baza danych

18 wierszy przekonwertowanych, 8 poprawek, brak odrzuconych

Pokaż

Tabele w pliku shop_2024.sqlZrzut MySQL 8.0.46 · zapisany przez mysqldump · utf8mb4

  • customers8 wierszy3
    7 kolumn
    idbigint not null
    namevarchar(100) not null
    emailvarchar(150) not null
    countryvarchar(2) not null
    is_activeboolean not null
    signed_update
    created_attimestamptz(0) not null
  • orders10 wierszy5
    9 kolumn
    idbigint not null
    customer_idbigint not null
    statustext not null
    totalnumeric(10,2) not null
    itemsinteger not null
    ordered_attimestamp(0) not null
    shipped_attimestamp(0)
    notevarchar(255)
    updated_attimestamptz(0) not null
-- Written by IntoSQL from a MySQL dump. Load it with: psql -v ON_ERROR_STOP=1 -f <file>
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SET check_function_bodies = false;
SET client_min_messages = warning;
SET synchronous_commit = off;
SET maintenance_work_mem = '512MB';

CREATE TABLE customers (
    id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL,
    name varchar(100) NOT NULL,
    email varchar(150) NOT NULL,
    country varchar(2) DEFAULT 'US' NOT NULL,
    is_active boolean DEFAULT true NOT NULL,
    signed_up date,
    created_at timestamptz(0) DEFAULT CURRENT_TIMESTAMP NOT NULL,
    CONSTRAINT customers_id_check CHECK (id >= 0)
);

CREATE TABLE orders (
    id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL,
    customer_id bigint NOT NULL,
    status text DEFAULT 'pending' NOT NULL,
    total numeric(10,2) NOT NULL,
    items integer DEFAULT 1 NOT NULL,
    ordered_at timestamp(0) NOT NULL,
    shipped_at timestamp(0),
    note varchar(255),
    updated_at timestamptz(0) DEFAULT CURRENT_TIMESTAMP NOT NULL,
    CONSTRAINT orders_id_check CHECK (id >= 0),
    CONSTRAINT orders_customer_id_check CHECK (customer_id >= 0),
    CONSTRAINT orders_status_check CHECK (status IN ('pending', 'paid', 'shipped', 'cancelled', '')),
    CONSTRAINT orders_items_check CHECK (items >= 0)
);

COPY customers (id, name, email, country, is_active, signed_up, created_at) FROM stdin;
1	Ana Martínez	ana@example.com	MX	t	2023-01-15	2023-01-15 10:24:00+00:00
2	Zoë Müller	zoe@example.de	DE	t	2023-02-03	2023-02-03 08:11:42+00:00
3	José Peña	jose@example.es	ES	f	2023-03-21	2023-03-21 19:05:17+00:00
4	李雷	lilei@example.cn	CN	t	2023-05-09	2023-05-09 02:40:00+00:00
5	Noah O'Brien	noah@example.ie	IE	t	\N	2023-06-30 14:00:00+00:00
6	Amélie Laurent	amelie@example.fr	FR	t	2024-01-02	2024-01-02 09:30:00+00:00
7	Ravi Patel	ravi@example.in	IN	f	2024-02-29	2024-02-29 23:59:59+00:00
8	Sofia Rossi 🌻	sofia@example.it	IT	t	2024-04-12	2024-04-12 12:12:12+00:00
\.

COPY orders (id, customer_id, status, total, items, ordered_at, shipped_at, note, updated_at) FROM stdin;
1	1	shipped	129.90	3	2024-03-01 10:00:00	2024-03-02 16:30:00	\N	2024-03-02 16:30:00+00:00
2	2	paid	54.00	1	2024-03-02 11:15:00	\N	Gift wrap 🎁	2024-03-02 11:20:00+00:00
3	1	cancelled	12.50	1	2024-03-03 09:45:00	\N	Customer changed their mind	2024-03-03 10:00:00+00:00
4	4	shipped	980.00	12	2024-03-05 02:10:00	2024-03-07 08:00:00	请小心轻放	2024-03-07 08:00:00+00:00
5	5	pending	45.75	2	2024-03-08 17:20:00	\N	Leave at the door; ring twice	2024-03-08 17:20:00+00:00
6	6	shipped	310.40	5	2024-03-10 13:00:00	2024-03-11 09:00:00	Fragile: "glass"	2024-03-11 09:00:00+00:00
7	8	paid	76.20	2	2024-03-11 18:45:00	\N	\N	2024-03-11 18:46:00+00:00
8	2		19.99	1	2024-03-12 08:00:00	\N	Status lost in an old import	2024-03-12 08:00:00+00:00
9	3	shipped	64.00	2	2024-03-14 15:30:00	\N	Shipping date never recorded	2024-03-15 10:00:00+00:00
10	7	paid	1499.00	1	2024-03-15 21:05:00	\N	C:\\Users\\ravi\\invoice.pdf	2024-03-15 21:05:00+00:00
\.


-- Keys, indexes and constraints, after the rows so each builds once.
CREATE UNIQUE INDEX customers_pkey ON customers (id);
CREATE UNIQUE INDEX customers_uq_email ON customers (email);
CREATE UNIQUE INDEX orders_pkey ON orders (id);
CREATE INDEX orders_idx_customer ON orders (customer_id);
CREATE INDEX orders_idx_status_date ON orders (status, ordered_at);
ALTER TABLE customers ADD CONSTRAINT customers_pkey PRIMARY KEY USING INDEX customers_pkey;
ALTER TABLE customers ADD CONSTRAINT customers_uq_email UNIQUE USING INDEX customers_uq_email;
ALTER TABLE orders ADD CONSTRAINT orders_pkey PRIMARY KEY USING INDEX orders_pkey;
ALTER TABLE orders ADD CONSTRAINT fk_orders_customer FOREIGN KEY (customer_id) REFERENCES customers (id) NOT VALID;
DO $f$ BEGIN
    ALTER TABLE orders VALIDATE CONSTRAINT fk_orders_customer;
EXCEPTION WHEN foreign_key_violation THEN
    RAISE WARNING 'foreign key % has rows without a parent: it stays NOT VALID, and new rows are checked', 'fk_orders_customer';
END $f$;
SELECT setval(pg_get_serial_sequence('customers', 'id'), LEAST(GREATEST(COALESCE((SELECT max(id) FROM customers)::numeric, 0) + 1, 1001), 9223372036854775807)::bigint, false);
COMMENT ON TABLE customers IS 'People who bought at least once';
SELECT setval(pg_get_serial_sequence('orders', 'id'), LEAST(GREATEST(COALESCE((SELECT max(id) FROM orders)::numeric, 0) + 1, 5001), 9223372036854775807)::bigint, false);
CREATE FUNCTION orders_updated_at_on_update() RETURNS trigger LANGUAGE plpgsql AS $f$
BEGIN
    IF NEW IS DISTINCT FROM OLD AND NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at THEN
        NEW.updated_at := CURRENT_TIMESTAMP;
    END IF;
    RETURN NEW;
END
$f$;
CREATE TRIGGER orders_updated_at_on_update BEFORE UPDATE ON orders FOR EACH ROW EXECUTE FUNCTION orders_updated_at_on_update();

Poprawki

  1. "id" w tabeli customers jest bez znaku, więc ma typ bigint z ograniczeniem CHECK, że nie jest ujemna.
  2. "signed_up" w tabeli customers dopuszcza teraz NULL: części jej wartości nie dało się zapisać i są NULL.
  3. Wartość domyślna "signed_up" w tabeli customers, 0000‑00‑00, nie jest datą akceptowaną przez PostgreSQL, więc kolumna nie ma wartości domyślnej.
  4. "customer_id" w tabeli orders jest bez znaku, więc ma typ bigint z ograniczeniem CHECK, że nie jest ujemna.
  5. "id" w tabeli orders jest bez znaku, więc ma typ bigint z ograniczeniem CHECK, że nie jest ujemna.
  6. "items" w tabeli orders jest bez znaku, więc ma typ integer z ograniczeniem CHECK, że nie jest ujemna.
  7. W "status" tabeli orders 1 wiersz zawiera pustą wartość, którą MySQL zapisuje dla błędnych danych; ograniczenie CHECK kolumny ją dopuszcza.
  8. "updated_at" w tabeli orders zmienia się na bieżący czas przy każdej aktualizacji; w PostgreSQL robi to wyzwalacz.

Do sprawdzenia

  • W "signed_up" tabeli customers zamieniono na NULL 1 wartość z zerową lub niemożliwą datą, np. 0000‑00‑00, bo PostgreSQL nie zapisuje takich dat. Jeśli te daty coś znaczą, zastąp je w źródle prawdziwymi, zanim zrobisz zrzut.
  • W "shipped_at" tabeli orders zamieniono na NULL 1 wartość z zerową lub niemożliwą datą, np. 0000‑00‑00 00:00:00, bo PostgreSQL nie zapisuje takich dat. Jeśli te daty coś znaczą, zastąp je w źródle prawdziwymi, zanim zrobisz zrzut.

Plik jest konwertowany na tym komputerze i nigdy nie jest wysyłany.

Inne przykłady:

Każda para baz danych

Wiersze to baza danych, z której pochodzi zrzut, kolumny to baza danych, dla której jest skrypt. Każda para ma własną stronę z konwerterem ustawionym dla niej, regułami, które stosuje, i opisem ładowania skryptu.

Typy danych dla każdej pary

Co jest zachowane, a co zgłaszane

Konwerter czyta sam zrzut, bez serwera bazy danych, i zapisuje skrypt na podstawie jego zawartości. Strona każdej pary wymienia reguły, które stosuje, od 25 do 67 na parę, z wpisem w raporcie, który dodaje każda z nich.

Zachowane w skrypcie

  • Tabele i kolumny, każda z najbliższym typem dostępnym w bazie docelowej oraz z jej długością i precyzją.
  • Klucze główne, unikalne i obce, indeksy i wartości domyślne.
  • Kolumny AUTO_INCREMENT, identity i serial, z identyfikatorem każdego wiersza i licznikiem kontynuowanym od miejsca, w którym zostawił go zrzut.
  • Każdy wiersz, z datami, liczbami dziesiętnymi, tekstem i wartościami binarnymi takimi, jakie są w zrzucie.

Wymienione w raporcie

  • Wartości, których baza docelowa nie przechowa bez zmian, na przykład data 0000-00-00 w PostgreSQL, z kolumną i liczbą wystąpień.invalid_date_null
  • Typy, których baza docelowa nie ma, na przykład ENUM lub INET6, z typem, którym każdy się stał.type_replaced
  • Widoki, wyzwalacze, procedury, funkcje i zdarzenia, z nazwy: są pisane we własnym języku każdej bazy danych, więc nie są konwertowane.not_converted_objects
  • Tekst, który nie jest poprawny w swoim zestawie znaków, oraz zrzuty, które już straciły znaki 4-bajtowe.invalid_utf8_replaced

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.
Strona MySQL do PostgreSQL

Wyeksportuj bazę danych, którą masz

Konwerter czyta plik, a nie działający serwer. Każda baza danych zapisuje go własnymi narzędziami:

Pytania o migrację bazy danych

Nie ma tu odpowiedzi? Napisz do nas przez stronę kontaktu, a odpowie człowiek. Strona kontaktu

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ń.

Z jakich wersji może pochodzić zrzut?

MySQL od 5.5 do 9, MariaDB od 10.3 do 12, PostgreSQL 10 i nowsze, SQL Server 2017 i nowsze, SQLite 3.0 i nowsze oraz Oracle 11g i nowsze. Strona każdej pary podaje, na których wersjach ładuje się jej skrypt.

Czy potrzebuję działającego serwera bazy danych?

Nie. Konwerter czyta sam plik zrzutu, więc źródłowa baza danych nie musi nigdzie działać. Skrypt ładuje się własnym klientem bazy docelowej, takim jak psql, mysql lub sqlcmd.

Co nie jest konwertowane?

Widoki, wyzwalacze, procedury składowane, funkcje i zdarzenia są pisane we własnym języku każdej bazy danych, więc zamiast tego raport wymienia je z nazwy. Tabele, klucze, indeksy i wiersze są w skrypcie.

Czy może załadować skrypt wprost do mojej bazy danych?

Aplikacja na komputer i polecenie intosql load zapisują wprost do SQLite za darmo, a do PostgreSQL, MySQL i MariaDB z IntoSQL Pro. W przypadku SQL Server i Oracle uruchom skrypt przez sqlcmd lub sqlplus.