本文へスキップ

MySQL を PostgreSQL に変換

mysqldump、mariadb-dump、mysqlpump、phpMyAdmin、Adminer で作成したダンプ (.sql または .sql.gz) をドロップすると、同じテーブル、キー、インデックス、データを持つ PostgreSQL スクリプトをダウンロードできます。PostgreSQL がそのまま保持できない値と、引き継がないオブジェクトは、すべてレポートに記載されます。

ファイル
sqlshop_2024.sqlサンプルファイル、5.1 KB
データベース

18 行を変換、修正 8 件、却下なし

表示

shop_2024.sql のテーブルMySQL 8.0.46 のダンプ · mysqldump で作成 · utf8mb4

  • customers8 行3
    7 列
    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 行5
    9 列
    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();

修正

  1. customers の "id" は符号なしのため、負でないことを確かめるチェック制約付きの bigint にしました。
  2. customers の "signed_up" は NULL を許可するようになりました。一部の値が保存できず、NULL になったためです。
  3. customers の "signed_up" のデフォルト値 0000‑00‑00 は PostgreSQL が受け付ける日付ではないため、列にデフォルト値はありません。
  4. orders の "customer_id" は符号なしのため、負でないことを確かめるチェック制約付きの bigint にしました。
  5. orders の "id" は符号なしのため、負でないことを確かめるチェック制約付きの bigint にしました。
  6. orders の "items" は符号なしのため、負でないことを確かめるチェック制約付きの integer にしました。
  7. orders の "status" の 1 行には、MySQL が無効な入力に対して保存する空の値があります。値のチェック制約はこの値を許可します。
  8. orders の "updated_at" は更新のたびに現在時刻に変わります。PostgreSQL ではトリガーがこれを行います。

確認が必要

  • customers の "signed_up" にある 1 個の値は、0000‑00‑00 のようなゼロ日付または存在しない日付で、PostgreSQL では保存できないため NULL にしました。 その日付に意味がある場合は、ダンプする前にソース側で実際の日付に置き換えてください。
  • orders の "shipped_at" にある 1 個の値は、0000‑00‑00 00:00:00 のようなゼロ日付または存在しない日付で、PostgreSQL では保存できないため NULL にしました。 その日付に意味がある場合は、ダンプする前にソース側で実際の日付に置き換えてください。

ファイルはこのコンピューター上で変換され、アップロードされることはありません。

その他のサンプル:

MySQL から PostgreSQL で変わること

各行はコンバーターが適用するルールです。ルールによってデータが変わったときにレポートに書かれる行も示します。

  • TINYINT(1), BOOL

    すべての値が 0 か 1 なら boolean、それ以外は smallint

    MySQL の BOOL は -128 から 127 までの任意の数を保持できる TINYINT(1) です。0 と 1 だけを持つ列は boolean になり、2 や -1 を持つ列は数値のままなので、意味が変わる値はありません。

    レポートの行: bool_kept_numeric

  • UNSIGNED integers

    負でないことを確かめる CHECK 付きの 1 段大きい整数型。BIGINT UNSIGNED は、すべての値が収まれば bigint、それ以外は numeric(20,0)

    PostgreSQL には符号なし整数がありません。より大きな型で符号なしの範囲全体を保持し、MySQL と同様にチェック制約で負の値を防ぎます。

    レポートの行: unsigned_widened

  • ZEROFILL and display widths

    削除

    ゼロ埋めは数値の表示方法であり、数値の一部ではありません。数値は残ります。ゼロ埋めが必要なら、読み出すときに書式を整えてください。

    レポートの行: zerofill_dropped

  • FLOAT(M,D)

    real または double precision、桁数指定なし

    PostgreSQL の浮動小数点数には固定の桁数がありません。保存された値はそのままコピーします。

    レポートの行: float_scale_dropped

  • BIT(1), BIT(n)

    boolean, bit(n)

    1 ビットははい/いいえを表し、それより幅の広いビット列はすべてのビットを保持します。

  • zero, partial or impossible dates (0000-00-00, 2024-02-30)

    NULL

    PostgreSQL は実在する暦の日付だけを保存します。MySQL は SQL モードが許せばゼロ日付や存在しない日付を保持しますが、これらは NULL になり、レポートでその数を示します。

    レポートの行: invalid_date_null

  • NOT NULL columns with values that become NULL

    NOT NULL を削除

    値を NULL にする必要があった列は NOT NULL を保てません。保つと読み込みが止まります。

    レポートの行: not_null_relaxed

  • DEFAULT '0000-00-00'

    デフォルト値なし

    PostgreSQL が保存できないデフォルト値は、架空の日付に置き換えずに省きます。

    レポートの行: zero_date_default

  • TIME

    すべての値が 1 日以内なら time、それ以外は interval

    MySQL の TIME は -838:59:59 から 838:59:59 までの期間です。値が 1 日に収まる列は時刻のままで、それより長い値や負の値を持つ列は interval になります。

    レポートの行: time_as_interval

  • YEAR

    範囲の CHECK 付きの smallint

    PostgreSQL には年の型がありません。チェック制約で、MySQL が許可するのと同じ値に限定します。

  • CHAR(n)

    varchar(n)

    MySQL は CHAR 値の末尾の空白を読み取り時に取り除きますが、PostgreSQL の char(n) は空白を付け直します。そのため varchar(n) にして、MySQL が返すとおりの値を保ちます。

  • DATETIME

    timestamp

    DATETIME はタイムゾーンを持たない時計の時刻で、PostgreSQL の timestamp と同じです。

  • TIMESTAMP

    ダンプが示すタイムゾーンでの timestamptz。示されていなければ UTC

    TIMESTAMP はある瞬間を表します。ダンプには書き出したときのタイムゾーンが示されます (mysqldump は UTC で書き出します)。示されていない場合は UTC として読み込み、レポートにその旨を記載します。

    レポートの行: timestamp_zone_assumed

  • ENUM

    値の CHECK 付きの text

    チェック制約付きの text は同じ値を保ち、PostgreSQL の enum 型より変更が簡単です。

  • ENUM holding '' (MySQL's error value)

    チェック制約が許可する空の値

    緩い SQL モードでは、無効な値が ENUM に入ると MySQL は空文字列を保存します。これらの行は残し、チェック制約でも許可します。

    レポートの行: enum_invalid_value

  • ENUM or SET holding values outside its list

    CHECK なし

    リストにない値はチェック制約に違反するため、チェック制約は作成しません。

    レポートの行: enum_check_skipped

  • SET

    すべての要素がリストにあることを確かめる CHECK 付きの text[]

    配列は各要素を別々に保つため、クエリで要素が含まれるかを調べられます。

  • JSON

    jsonb。値に \u0000 があれば json

    jsonb は PostgreSQL でインデックスやクエリに適した型ですが、\u0000 エスケープを受け付けないため、これを含む列は json のままです。

    レポートの行: json_not_jsonb

  • NUL bytes in text

    削除

    PostgreSQL のテキストは NUL バイトを保持できません。そのバイトを取り除き、レポートで該当する値の数を示します。

    レポートの行: nul_removed

  • text that isn't valid in its character set

    不正なバイトを置換文字に

    PostgreSQL のテキストは有効な UTF-8 である必要があります。

    レポートの行: invalid_utf8_replaced

  • text decoded twice (ñ)

    そのままコピー

    ダンプにはまさにこの文字が含まれているため、そのままコピーし、レポートで指摘します。

    レポートの行: mojibake_suspected

  • AUTO_INCREMENT

    GENERATED BY DEFAULT AS IDENTITY、カウンターはコピーした ID の後から

    IDENTITY 列はコピーした ID を受け付け、カウンターは最大の ID かダンプの AUTO_INCREMENT のうち大きい方の後から続きます。

  • MyISAM AUTO_INCREMENT on the second column of a key

    テーブルに 1 つのカウンター

    MyISAM はキーの最初の列のグループごとに採番します。PostgreSQL では列ごとにカウンターは 1 つです。

    レポートの行: myisam_group_autoincrement

  • ON UPDATE CURRENT_TIMESTAMP

    BEFORE UPDATE トリガー

    行が変更され、更新でその列が設定されなかった場合、MySQL と同様にトリガーが列を現在時刻にします。

    レポートの行: on_update_trigger

  • generated columns

    STORED

    PostgreSQL 13 から 17 は生成列を保存する方式だけに対応しています。式は同じです。

    レポートの行: virtual_as_stored

  • generated columns with functions PostgreSQL lacks

    普通の列

    PostgreSQL 用に書き換えられない式は、普通の列とレポートの 1 行になります。

    レポートの行: generated_not_translated

  • INVISIBLE columns

    通常の列

    PostgreSQL には非表示の列がありません。

    レポートの行: invisible_column

  • CHECK constraints

    変換して CREATE TABLE 内に記述

    CREATE TABLE 内のチェック制約は、後でチェックごとにスキャンするのではなく、各行の読み込み時に検証されます。

  • CHECK constraints with functions PostgreSQL lacks

    作成しない

    PostgreSQL 用に書き換えられないチェック制約は省き、レポートに記載します。

    レポートの行: check_skipped

  • CHECK ... NOT ENFORCED

    作成しない

    MySQL はこれらのチェック制約を適用せずに保持するため、違反する行がある可能性があります。

    レポートの行: check_not_enforced

  • defaults with functions PostgreSQL lacks

    デフォルト値なし

    PostgreSQL 用に書き換えられないデフォルト値は省き、レポートに記載します。

    レポートの行: default_not_translated

  • keys and indexes on a prefix, c(20)

    left(c, 20) のインデックス

    PostgreSQL は式にインデックスを作れるため、同じ先頭部分にインデックスを作ります。

    レポートの行: prefix_unique

  • FULLTEXT indexes

    to_tsvector('simple', ...) の GIN

    全文検索では MATCH ... AGAINST の代わりに @@ を使います。

    レポートの行: fulltext_as_gin

  • indexes on values over 2,000 bytes

    hash

    btree のエントリにはそれほど長い値を入れられません。hash インデックスなら等しい値を検索できます。

    レポートの行: index_on_wide_values

  • SPATIAL indexes

    PostGIS がなければ作成しない

    空間インデックスには PostGIS が必要です。

    レポートの行: spatial_index_skipped

  • functional indexes PostgreSQL can't write

    作成しない

    PostgreSQL 用に書き換えられない式のインデックスは省き、レポートに記載します。

    レポートの行: index_skipped

  • foreign keys

    データの後に NOT VALID で作成してから検証し、孤立した行があれば警告

    ダンプは FOREIGN_KEY_CHECKS=0 で読み込まれ、MyISAM はチェックを行わないため、親のない行はよくあります。キーを先に作成し、最後に検証します。孤立した行があれば、読み込みを止めずにキーを NOT VALID のまま残して警告します。

  • foreign keys to columns without a unique key

    作成しない

    PostgreSQL では参照先の列に一意キーが必要ですが、InnoDB では不要です。

    レポートの行: foreign_key_skipped

  • table and column names

    一意のままなら小文字

    小文字の名前は PostgreSQL で引用符なしで書けます。

    レポートの行: identifier_renamed

  • names over 63 bytes

    ハッシュを付けて短縮

    PostgreSQL の名前は 63 バイトまでです。ハッシュにより、短縮した名前どうしが重なりません。

    レポートの行: name_shortened

  • GEOMETRY, POINT, POLYGON...

    bytea に WKB

    PostGIS がなくても、標準の WKB (Well-Known Binary) ですべてのジオメトリを正確に保持します。

    レポートの行: geometry_as_wkb

  • INET4, INET6, UUID (MariaDB)

    inet, uuid

    PostgreSQL にも同じ型があります。

  • BINARY, VARBINARY, BLOB

    bytea

    バイトはバイトのままです。

  • PARTITION BY

    1 つのテーブル

    行は同じです。必要なら PostgreSQL でもう一度テーブルをパーティション分割してください。

    レポートの行: partitions_dropped

  • WITH SYSTEM VERSIONING (MariaDB)

    現在の行を持つテーブル

    ダンプには現在の行しか含まれません。

    レポートの行: system_versioning_dropped

  • MyISAM, MEMORY and other engines

    通常のテーブル

    PostgreSQL のテーブルエンジンは 1 つだけです。

    レポートの行: engine_dropped

  • views, triggers, procedures, functions and events

    レポートに記載

    これらのコードは MySQL の言語で書かれているため、作り直せるよう一覧にします。

    レポートの行: not_converted_objects

  • dumps without CREATE TABLE

    値から読み取った型

    --no-create-info で作成したダンプには行しかないため、型は値から決まります。

    レポートの行: no_schema

  • geometries in a dump without CREATE TABLE

    bytea に WKB

    MySQL のジオメトリ形式を値から認識し、標準の WKB として保存します。

    レポートの行: geometry_inferred

  • _ci collations

    厳密な比較

    PostgreSQL は、指定がない限りテキストを厳密に比較します。

    レポートの行: case_insensitive_collation

  • SET NAMES utf8 from utf8mb4 tables

    変換し、警告を表示

    MySQL 5.x の mysqldump は既定で 3 バイトの utf8 で書き出し、コンバーターがファイルを読む前にすべての絵文字を疑問符に置き換えます。

    レポートの行: dump_lost_four_byte_chars

  • dumps without SET NAMES whose text isn't UTF-8

    Latin-1 (Windows-1252) として読み込み

    MySQL の latin1 は Windows-1252 で、こうしたダンプでよく使われる文字コードです。

    レポートの行: charset_guessed

  • sjis, cp932, gbk, big5 dumps

    UTF-8 として読み込み、警告を表示

    これらの文字コードはまだデコードできません。

    レポートの行: unsupported_charset

  • UNHEX('..'), CONVERT(b'..', UNSIGNED), CONVERT(".." USING x), ST_GeomFromText('..') in rows

    評価

    一部のダンプツールは値をこうした関数呼び出しとして書き出します。これらは生成される値として読み込み、地理座標の WKT は経度を先にします。

  • other expressions in rows

    NULL

    データベースを実行しないコンバーターでは、これらを評価できません。

    レポートの行: expression_value

  • DEFAULT in VALUES

    列のデフォルト値

    リテラルのデフォルト値を行にコピーします。

    レポートの行: default_keyword_filled

  • DEFAULT in VALUES without a literal default

    NULL

    コピーする値がありません。

    レポートの行: default_keyword_null

  • REPLACE and INSERT IGNORE

    通常の行

    ダンプではキーごとに 1 行なので、行は同じです。

    レポートの行: replace_as_insert

  • types IntoSQL doesn't know

    text

    text はどんな値も保持できます。読み込み後に型を変更してください。

    レポートの行: unknown_type

  • values that don't fit their column

    NULL

    破損したダンプや手書きのダンプには、列が保持できない値が含まれることがあります。それらを NULL にして、残りを読み込みます。

    レポートの行: invalid_value_null

  • unreadable geometries

    NULL

    ジオメトリでないバイト列は、ジオメトリとして保存できません。

    レポートの行: bad_geometry

  • CREATE SEQUENCE (MariaDB)

    現在の値を持つ CREATE SEQUENCE

    PostgreSQL のシーケンスも同じオプションを使えます。

MySQL ではPostgreSQL ではレポートの行
TINYINT(1), BOOLすべての値が 0 か 1 なら boolean、それ以外は smallintMySQL の BOOL は -128 から 127 までの任意の数を保持できる TINYINT(1) です。0 と 1 だけを持つ列は boolean になり、2 や -1 を持つ列は数値のままなので、意味が変わる値はありません。bool_kept_numeric
UNSIGNED integers負でないことを確かめる CHECK 付きの 1 段大きい整数型。BIGINT UNSIGNED は、すべての値が収まれば bigint、それ以外は numeric(20,0)PostgreSQL には符号なし整数がありません。より大きな型で符号なしの範囲全体を保持し、MySQL と同様にチェック制約で負の値を防ぎます。unsigned_widened
ZEROFILL and display widths削除ゼロ埋めは数値の表示方法であり、数値の一部ではありません。数値は残ります。ゼロ埋めが必要なら、読み出すときに書式を整えてください。zerofill_dropped
FLOAT(M,D)real または double precision、桁数指定なしPostgreSQL の浮動小数点数には固定の桁数がありません。保存された値はそのままコピーします。float_scale_dropped
BIT(1), BIT(n)boolean, bit(n)1 ビットははい/いいえを表し、それより幅の広いビット列はすべてのビットを保持します。
zero, partial or impossible dates (0000-00-00, 2024-02-30)NULLPostgreSQL は実在する暦の日付だけを保存します。MySQL は SQL モードが許せばゼロ日付や存在しない日付を保持しますが、これらは NULL になり、レポートでその数を示します。invalid_date_null
NOT NULL columns with values that become NULLNOT NULL を削除値を NULL にする必要があった列は NOT NULL を保てません。保つと読み込みが止まります。not_null_relaxed
DEFAULT '0000-00-00'デフォルト値なしPostgreSQL が保存できないデフォルト値は、架空の日付に置き換えずに省きます。zero_date_default
TIMEすべての値が 1 日以内なら time、それ以外は intervalMySQL の TIME は -838:59:59 から 838:59:59 までの期間です。値が 1 日に収まる列は時刻のままで、それより長い値や負の値を持つ列は interval になります。time_as_interval
YEAR範囲の CHECK 付きの smallintPostgreSQL には年の型がありません。チェック制約で、MySQL が許可するのと同じ値に限定します。
CHAR(n)varchar(n)MySQL は CHAR 値の末尾の空白を読み取り時に取り除きますが、PostgreSQL の char(n) は空白を付け直します。そのため varchar(n) にして、MySQL が返すとおりの値を保ちます。
DATETIMEtimestampDATETIME はタイムゾーンを持たない時計の時刻で、PostgreSQL の timestamp と同じです。
TIMESTAMPダンプが示すタイムゾーンでの timestamptz。示されていなければ UTCTIMESTAMP はある瞬間を表します。ダンプには書き出したときのタイムゾーンが示されます (mysqldump は UTC で書き出します)。示されていない場合は UTC として読み込み、レポートにその旨を記載します。timestamp_zone_assumed
ENUM値の CHECK 付きの textチェック制約付きの text は同じ値を保ち、PostgreSQL の enum 型より変更が簡単です。
ENUM holding '' (MySQL's error value)チェック制約が許可する空の値緩い SQL モードでは、無効な値が ENUM に入ると MySQL は空文字列を保存します。これらの行は残し、チェック制約でも許可します。enum_invalid_value
ENUM or SET holding values outside its listCHECK なしリストにない値はチェック制約に違反するため、チェック制約は作成しません。enum_check_skipped
SETすべての要素がリストにあることを確かめる CHECK 付きの text[]配列は各要素を別々に保つため、クエリで要素が含まれるかを調べられます。
JSONjsonb。値に \u0000 があれば jsonjsonb は PostgreSQL でインデックスやクエリに適した型ですが、\u0000 エスケープを受け付けないため、これを含む列は json のままです。json_not_jsonb
NUL bytes in text削除PostgreSQL のテキストは NUL バイトを保持できません。そのバイトを取り除き、レポートで該当する値の数を示します。nul_removed
text that isn't valid in its character set不正なバイトを置換文字にPostgreSQL のテキストは有効な UTF-8 である必要があります。invalid_utf8_replaced
text decoded twice (ñ)そのままコピーダンプにはまさにこの文字が含まれているため、そのままコピーし、レポートで指摘します。mojibake_suspected
AUTO_INCREMENTGENERATED BY DEFAULT AS IDENTITY、カウンターはコピーした ID の後からIDENTITY 列はコピーした ID を受け付け、カウンターは最大の ID かダンプの AUTO_INCREMENT のうち大きい方の後から続きます。
MyISAM AUTO_INCREMENT on the second column of a keyテーブルに 1 つのカウンターMyISAM はキーの最初の列のグループごとに採番します。PostgreSQL では列ごとにカウンターは 1 つです。myisam_group_autoincrement
ON UPDATE CURRENT_TIMESTAMPBEFORE UPDATE トリガー行が変更され、更新でその列が設定されなかった場合、MySQL と同様にトリガーが列を現在時刻にします。on_update_trigger
generated columnsSTOREDPostgreSQL 13 から 17 は生成列を保存する方式だけに対応しています。式は同じです。virtual_as_stored
generated columns with functions PostgreSQL lacks普通の列PostgreSQL 用に書き換えられない式は、普通の列とレポートの 1 行になります。generated_not_translated
INVISIBLE columns通常の列PostgreSQL には非表示の列がありません。invisible_column
CHECK constraints変換して CREATE TABLE 内に記述CREATE TABLE 内のチェック制約は、後でチェックごとにスキャンするのではなく、各行の読み込み時に検証されます。
CHECK constraints with functions PostgreSQL lacks作成しないPostgreSQL 用に書き換えられないチェック制約は省き、レポートに記載します。check_skipped
CHECK ... NOT ENFORCED作成しないMySQL はこれらのチェック制約を適用せずに保持するため、違反する行がある可能性があります。check_not_enforced
defaults with functions PostgreSQL lacksデフォルト値なしPostgreSQL 用に書き換えられないデフォルト値は省き、レポートに記載します。default_not_translated
keys and indexes on a prefix, c(20)left(c, 20) のインデックスPostgreSQL は式にインデックスを作れるため、同じ先頭部分にインデックスを作ります。prefix_unique
FULLTEXT indexesto_tsvector('simple', ...) の GIN全文検索では MATCH ... AGAINST の代わりに @@ を使います。fulltext_as_gin
indexes on values over 2,000 byteshashbtree のエントリにはそれほど長い値を入れられません。hash インデックスなら等しい値を検索できます。index_on_wide_values
SPATIAL indexesPostGIS がなければ作成しない空間インデックスには PostGIS が必要です。spatial_index_skipped
functional indexes PostgreSQL can't write作成しないPostgreSQL 用に書き換えられない式のインデックスは省き、レポートに記載します。index_skipped
foreign keysデータの後に NOT VALID で作成してから検証し、孤立した行があれば警告ダンプは FOREIGN_KEY_CHECKS=0 で読み込まれ、MyISAM はチェックを行わないため、親のない行はよくあります。キーを先に作成し、最後に検証します。孤立した行があれば、読み込みを止めずにキーを NOT VALID のまま残して警告します。
foreign keys to columns without a unique key作成しないPostgreSQL では参照先の列に一意キーが必要ですが、InnoDB では不要です。foreign_key_skipped
table and column names一意のままなら小文字小文字の名前は PostgreSQL で引用符なしで書けます。identifier_renamed
names over 63 bytesハッシュを付けて短縮PostgreSQL の名前は 63 バイトまでです。ハッシュにより、短縮した名前どうしが重なりません。name_shortened
GEOMETRY, POINT, POLYGON...bytea に WKBPostGIS がなくても、標準の WKB (Well-Known Binary) ですべてのジオメトリを正確に保持します。geometry_as_wkb
INET4, INET6, UUID (MariaDB)inet, uuidPostgreSQL にも同じ型があります。
BINARY, VARBINARY, BLOBbyteaバイトはバイトのままです。
PARTITION BY1 つのテーブル行は同じです。必要なら PostgreSQL でもう一度テーブルをパーティション分割してください。partitions_dropped
WITH SYSTEM VERSIONING (MariaDB)現在の行を持つテーブルダンプには現在の行しか含まれません。system_versioning_dropped
MyISAM, MEMORY and other engines通常のテーブルPostgreSQL のテーブルエンジンは 1 つだけです。engine_dropped
views, triggers, procedures, functions and eventsレポートに記載これらのコードは MySQL の言語で書かれているため、作り直せるよう一覧にします。not_converted_objects
dumps without CREATE TABLE値から読み取った型--no-create-info で作成したダンプには行しかないため、型は値から決まります。no_schema
geometries in a dump without CREATE TABLEbytea に WKBMySQL のジオメトリ形式を値から認識し、標準の WKB として保存します。geometry_inferred
_ci collations厳密な比較PostgreSQL は、指定がない限りテキストを厳密に比較します。case_insensitive_collation
SET NAMES utf8 from utf8mb4 tables変換し、警告を表示MySQL 5.x の mysqldump は既定で 3 バイトの utf8 で書き出し、コンバーターがファイルを読む前にすべての絵文字を疑問符に置き換えます。dump_lost_four_byte_chars
dumps without SET NAMES whose text isn't UTF-8Latin-1 (Windows-1252) として読み込みMySQL の latin1 は Windows-1252 で、こうしたダンプでよく使われる文字コードです。charset_guessed
sjis, cp932, gbk, big5 dumpsUTF-8 として読み込み、警告を表示これらの文字コードはまだデコードできません。unsupported_charset
UNHEX('..'), CONVERT(b'..', UNSIGNED), CONVERT(".." USING x), ST_GeomFromText('..') in rows評価一部のダンプツールは値をこうした関数呼び出しとして書き出します。これらは生成される値として読み込み、地理座標の WKT は経度を先にします。
other expressions in rowsNULLデータベースを実行しないコンバーターでは、これらを評価できません。expression_value
DEFAULT in VALUES列のデフォルト値リテラルのデフォルト値を行にコピーします。default_keyword_filled
DEFAULT in VALUES without a literal defaultNULLコピーする値がありません。default_keyword_null
REPLACE and INSERT IGNORE通常の行ダンプではキーごとに 1 行なので、行は同じです。replace_as_insert
types IntoSQL doesn't knowtexttext はどんな値も保持できます。読み込み後に型を変更してください。unknown_type
values that don't fit their columnNULL破損したダンプや手書きのダンプには、列が保持できない値が含まれることがあります。それらを NULL にして、残りを読み込みます。invalid_value_null
unreadable geometriesNULLジオメトリでないバイト列は、ジオメトリとして保存できません。bad_geometry
CREATE SEQUENCE (MariaDB)現在の値を持つ CREATE SEQUENCEPostgreSQL のシーケンスも同じオプションを使えます。

スクリプトを PostgreSQL に読み込む

スクリプトはテーブルを作成して行をコピーしてから、キー、インデックス、外部キーを追加します。そのため読み込みが速く、最初のエラーで止まります。

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

外部キーは NOT VALID で追加してから検証します。存在しない行を参照している行があれば、途中で失敗する代わりに、どの制約かをスクリプトが示します。

大きなダンプでは、先にデータベースを作成し、サーバーと同じマシンから psql でスクリプトを実行してください。

MySQL を最適な方法でダンプする

コンバーターはダンプの内容を読み取ります。次のオプションを使うと、より多くのデータがダンプに残ります。

  • --default-character-set=utf8mb4 を使うと、絵文字などの 4 バイト文字が残ります。utf8 のダンプでは、コンバーターが読む前にこれらの文字が失われます。
  • --hex-blob はバイナリ列を 16 進数で書き出すため、システム間でコピーしても壊れません。
  • --routines --triggers --events を使うとこれらのオブジェクトがダンプに含まれ、レポートに一覧できます。

変換されないもの

ビュー、トリガー、ストアドプロシージャ、関数、イベントは、データベースごとに独自の言語で書かれます。黙って削除されることはなく、レポートに名前で一覧されるので、PostgreSQL 用に書き直せます。

pgloader との比較

同じダンプを IntoSQL と pgloader 3.6.7 で変換して読み込み、1 台のマシン (SATA SSD 搭載の 10 コア i9-10900K) で 2026 年 10 月に測定しました。

  • 2、-1、-5 を持つ TINYINT(1) 列: pgloader は警告なしに、すべてを true として読み込みます。IntoSQL は数値を保ち、レポートにその理由が書かれます。
  • 'it's' というデフォルト値、バッククォートを含む名前のテーブル、空の値を持つ ENUM、24 時間を超える TIME を含むダンプ: pgloader は止まります。IntoSQL は変換して読み込みます。
  • pgloader で読み込んだ結果では、主キー、一意キー、外部キー、IDENTITY が失われています。IntoSQL はすべて保持します。
  • 3000 万行、5.3 GB のダンプ: pgloader は先に稼働中の MySQL への復元が必要で、それに 18 分かかり、その後デフォルト設定ではメモリ不足になります。IntoSQL はダンプを 10 秒で変換し、psql はスクリプトを約 3 分で読み込みます。
  • MySQL 5.5 から 9、MariaDB 10.3 から 12 の 476 個のダンプを PostgreSQL 13 と 18 に読み込みました。読み込みエラーはなく、レポートに記載されずに変わった値もありません。

MySQL から PostgreSQL への変換に関する質問

ここに答えがない場合は、お問い合わせページからご連絡ください。担当者が返信します。 お問い合わせページ

ダンプはアップロードされますか?

いいえ。コンバーターはブラウザ上で動作し、ダンプをディスクから少しずつ読み込むため、ダンプがコンピューターの外に出ることはありません。デスクトップアプリとコマンドラインも、お使いのコンピューター上で変換します。

ダンプはどのくらいの大きさまで扱えますか?

コンバーターはダンプ全体をメモリに保持しません。ファイルを範囲ごとに 2 回読み、読みながらスクリプトを書き出します。数 GB のダンプも、ブラウザ、デスクトップアプリ、コマンドラインで変換できます。

MariaDB のダンプも読み込めますか?

はい。mariadb-dump や MariaDB 10.3 から 12 のダンプも同じ方法で変換されます。MariaDB の INET6、INET4、UUID 列も対象です。

0000-00-00 の日付はどうなりますか?

PostgreSQL にはゼロ日付がないため、NULL になり、列は NULL を許可します。各列にいくつあったかはレポートに記載されます。

AUTO_INCREMENT の値は保持されますか?

はい。各 AUTO_INCREMENT 列は IDENTITY 列になり、すべての行が ID を保ちます。次の ID は最大の ID の後から、テーブルの AUTO_INCREMENT の方が大きければその後から続きます。

TINYINT(1) は boolean になりますか?

列のすべての値が 0 か 1 の場合だけです。2 や -1 など他の数がある場合は数値のままで、レポートにその理由が書かれるため、誤って true になる値はありません。

ストアドプロシージャやトリガーはどうなりますか?

データベースごとに独自の言語で書かれるため、変換はせず、レポートに名前で一覧します。例外は ON UPDATE CURRENT_TIMESTAMP で、PostgreSQL のトリガーになります。

スクリプトはどの PostgreSQL バージョンで読み込めますか?

PostgreSQL 13 から 18 です。どのバージョンでも同じスクリプトを読み込め、問題があれば最初のエラーで止まります。