MySQL を Oracle に変換
mysqldump、mariadb-dump、mysqlpump、phpMyAdmin、Adminer で作成したダンプ (.sql または .sql.gz) をドロップすると、同じテーブル、キー、インデックス、データを持つ Oracle スクリプトをダウンロードできます。Oracle がそのまま保持できない値と、引き継がないオブジェクトは、すべてレポートに記載されます。
18 行を変換、修正 4 件、却下なし
shop_2024.sql のテーブルMySQL 8.0.46 のダンプ · mysqldump で作成 · utf8mb4
customersCUSTOMERS として書き出し8 行2
7 列 ID NUMBER(10) not null NAME VARCHAR2(100 CHAR) not null EMAIL VARCHAR2(150 CHAR) not null COUNTRY VARCHAR2(2 CHAR) not null IS_ACTIVE NUMBER(1) not null SIGNED_UP DATE CREATED_AT TIMESTAMP(0) WITH TIME ZONE not null ordersORDERS として書き出し10 行2
9 列 ID NUMBER(10) not null CUSTOMER_ID NUMBER(10) not null STATUS VARCHAR2(9 CHAR) TOTAL NUMBER(10,2) not null ITEMS NUMBER(5) not null ORDERED_AT TIMESTAMP(0) not null SHIPPED_AT TIMESTAMP(0) NOTE VARCHAR2(255 CHAR) UPDATED_AT TIMESTAMP(0) WITH TIME ZONE not null
-- Written by IntoSQL from a MySQL dump. Load it with: NLS_LANG=.AL32UTF8 sqlplus -S -L <user>/<password>@<database> @<file>
WHENEVER SQLERROR EXIT FAILURE ROLLBACK;
SET DEFINE OFF;
SET SQLBLANKLINES ON;
SET FEEDBACK OFF;
SET SERVEROUTPUT ON;
CREATE OR REPLACE FUNCTION "INTOSQL_CLOB" (p SYS.ODCIVARCHAR2LIST) RETURN CLOB IS
r CLOB;
BEGIN
DBMS_LOB.CREATETEMPORARY(r, TRUE);
FOR i IN 1 .. p.COUNT LOOP
IF p(i) IS NOT NULL THEN
DBMS_LOB.WRITEAPPEND(r, LENGTH2(p(i)), p(i));
END IF;
END LOOP;
RETURN r;
END;
/
CREATE OR REPLACE FUNCTION "INTOSQL_BLOB" (p SYS.ODCIVARCHAR2LIST) RETURN BLOB IS
r BLOB;
piece RAW(2000);
BEGIN
DBMS_LOB.CREATETEMPORARY(r, TRUE);
FOR i IN 1 .. p.COUNT LOOP
piece := HEXTORAW(p(i));
DBMS_LOB.WRITEAPPEND(r, UTL_RAW.LENGTH(piece), piece);
END LOOP;
RETURN r;
END;
/
CREATE TABLE "CUSTOMERS" (
"ID" NUMBER(10) GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH 1001),
"NAME" VARCHAR2(100 CHAR) NOT NULL,
"EMAIL" VARCHAR2(150 CHAR) NOT NULL,
"COUNTRY" VARCHAR2(2 CHAR) DEFAULT 'US' NOT NULL,
"IS_ACTIVE" NUMBER(1) DEFAULT 1 NOT NULL,
"SIGNED_UP" DATE,
"CREATED_AT" TIMESTAMP(0) WITH TIME ZONE DEFAULT SYSTIMESTAMP NOT NULL,
CONSTRAINT "CK_CUSTOMERS_ID" CHECK ("ID" >= 0),
CONSTRAINT "CK_CUSTOMERS_IS_ACTIVE" CHECK ("IS_ACTIVE" IN (0, 1))
);
CREATE TABLE "ORDERS" (
"ID" NUMBER(10) GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH 5001),
"CUSTOMER_ID" NUMBER(10) NOT NULL,
"STATUS" VARCHAR2(9 CHAR) DEFAULT 'pending',
"TOTAL" NUMBER(10,2) NOT NULL,
"ITEMS" NUMBER(5) DEFAULT 1 NOT NULL,
"ORDERED_AT" TIMESTAMP(0) NOT NULL,
"SHIPPED_AT" TIMESTAMP(0),
"NOTE" VARCHAR2(255 CHAR),
"UPDATED_AT" TIMESTAMP(0) WITH TIME ZONE DEFAULT SYSTIMESTAMP NOT NULL,
CONSTRAINT "CK_ORDERS_ID" CHECK ("ID" >= 0),
CONSTRAINT "CK_ORDERS_CUSTOMER_ID" CHECK ("CUSTOMER_ID" >= 0),
CONSTRAINT "CK_ORDERS_STATUS" CHECK ("STATUS" IN ('pending', 'paid', 'shipped', 'cancelled')),
CONSTRAINT "CK_ORDERS_ITEMS" CHECK ("ITEMS" >= 0)
);
BEGIN
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
1,
'Ana Martínez',
'ana@example.com',
'MX',
1,
DATE '2023-01-15',
TIMESTAMP '2023-01-15 10:24:00 +00:00'
);
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
2,
'Zoë Müller',
'zoe@example.de',
'DE',
1,
DATE '2023-02-03',
TIMESTAMP '2023-02-03 08:11:42 +00:00'
);
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
3,
'José Peña',
'jose@example.es',
'ES',
0,
DATE '2023-03-21',
TIMESTAMP '2023-03-21 19:05:17 +00:00'
);
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
4,
'李雷',
'lilei@example.cn',
'CN',
1,
DATE '2023-05-09',
TIMESTAMP '2023-05-09 02:40:00 +00:00'
);
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
5,
'Noah O''Brien',
'noah@example.ie',
'IE',
1,
NULL,
TIMESTAMP '2023-06-30 14:00:00 +00:00'
);
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
6,
'Amélie Laurent',
'amelie@example.fr',
'FR',
1,
DATE '2024-01-02',
TIMESTAMP '2024-01-02 09:30:00 +00:00'
);
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
7,
'Ravi Patel',
'ravi@example.in',
'IN',
0,
DATE '2024-02-29',
TIMESTAMP '2024-02-29 23:59:59 +00:00'
);
INSERT INTO "CUSTOMERS" (
"ID",
"NAME",
"EMAIL",
"COUNTRY",
"IS_ACTIVE",
"SIGNED_UP",
"CREATED_AT"
) VALUES (
8,
'Sofia Rossi 🌻',
'sofia@example.it',
'IT',
1,
DATE '2024-04-12',
TIMESTAMP '2024-04-12 12:12:12 +00:00'
);
COMMIT;
END;
/
BEGIN
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"UPDATED_AT"
) VALUES (
1,
1,
'shipped',
129.90,
3,
TIMESTAMP '2024-03-01 10:00:00',
TIMESTAMP '2024-03-02 16:30:00',
NULL,
TIMESTAMP '2024-03-02 16:30:00 +00:00'
);
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"UPDATED_AT"
) VALUES (
2,
2,
'paid',
54.00,
1,
TIMESTAMP '2024-03-02 11:15:00',
NULL,
'Gift wrap 🎁',
TIMESTAMP '2024-03-02 11:20:00 +00:00'
);
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"UPDATED_AT"
) VALUES (
3,
1,
'cancelled',
12.50,
1,
TIMESTAMP '2024-03-03 09:45:00',
NULL,
'Customer changed their mind',
TIMESTAMP '2024-03-03 10:00:00 +00:00'
);
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"UPDATED_AT"
) VALUES (
4,
4,
'shipped',
980.00,
12,
TIMESTAMP '2024-03-05 02:10:00',
TIMESTAMP '2024-03-07 08:00:00',
'请小心轻放',
TIMESTAMP '2024-03-07 08:00:00 +00:00'
);
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"UPDATED_AT"
) VALUES (
5,
5,
'pending',
45.75,
2,
TIMESTAMP '2024-03-08 17:20:00',
NULL,
'Leave at the door; ring twice',
TIMESTAMP '2024-03-08 17:20:00 +00:00'
);
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"UPDATED_AT"
) VALUES (
6,
6,
'shipped',
310.40,
5,
TIMESTAMP '2024-03-10 13:00:00',
TIMESTAMP '2024-03-11 09:00:00',
'Fragile: "glass"',
TIMESTAMP '2024-03-11 09:00:00 +00:00'
);
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"UPDATED_AT"
) VALUES (
7,
8,
'paid',
76.20,
2,
TIMESTAMP '2024-03-11 18:45:00',
NULL,
NULL,
TIMESTAMP '2024-03-11 18:46:00 +00:00'
);
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"UPDATED_AT"
) VALUES (
8,
2,
NULL,
19.99,
1,
TIMESTAMP '2024-03-12 08:00:00',
NULL,
'Status lost in an old import',
TIMESTAMP '2024-03-12 08:00:00 +00:00'
);
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"UPDATED_AT"
) VALUES (
9,
3,
'shipped',
64.00,
2,
TIMESTAMP '2024-03-14 15:30:00',
NULL,
'Shipping date never recorded',
TIMESTAMP '2024-03-15 10:00:00 +00:00'
);
INSERT INTO "ORDERS" (
"ID",
"CUSTOMER_ID",
"STATUS",
"TOTAL",
"ITEMS",
"ORDERED_AT",
"SHIPPED_AT",
"NOTE",
"UPDATED_AT"
) VALUES (
10,
7,
'paid',
1499.00,
1,
TIMESTAMP '2024-03-15 21:05:00',
NULL,
'C:\Users\ravi\invoice.pdf',
TIMESTAMP '2024-03-15 21:05:00 +00:00'
);
COMMIT;
END;
/
-- Keys, indexes, foreign keys, counters and triggers, after the rows.
ALTER TABLE "CUSTOMERS" ADD CONSTRAINT "PK_CUSTOMERS" PRIMARY KEY ("ID");
ALTER TABLE "CUSTOMERS" ADD CONSTRAINT "UQ_CUSTOMERS_UQ_EMAIL" UNIQUE ("EMAIL");
ALTER TABLE "ORDERS" ADD CONSTRAINT "PK_ORDERS" PRIMARY KEY ("ID");
CREATE INDEX "IX_ORDERS_IDX_CUSTOMER" ON "ORDERS" ("CUSTOMER_ID");
CREATE INDEX "IX_ORDERS_IDX_STATUS_DATE" ON "ORDERS" ("STATUS", "ORDERED_AT");
ALTER TABLE "ORDERS" ADD CONSTRAINT "FK_ORDERS_CUSTOMER" FOREIGN KEY ("CUSTOMER_ID") REFERENCES "CUSTOMERS" ("ID") ENABLE NOVALIDATE;
BEGIN
EXECUTE IMMEDIATE 'ALTER TABLE "ORDERS" ENABLE VALIDATE CONSTRAINT "FK_ORDERS_CUSTOMER"';
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Foreign key ' || '"FK_ORDERS_CUSTOMER"' || ' has rows without a parent: it stays unvalidated, and new rows are checked.');
END;
/
DECLARE
next_id NUMBER;
BEGIN
SELECT NVL(MAX("ID"), 0) + 1 INTO next_id FROM "CUSTOMERS";
IF next_id < 1001 THEN
next_id := 1001;
END IF;
EXECUTE IMMEDIATE 'ALTER TABLE "CUSTOMERS" MODIFY ("ID" GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH ' || next_id || '))';
END;
/
COMMENT ON TABLE "CUSTOMERS" IS 'People who bought at least once';
DECLARE
next_id NUMBER;
BEGIN
SELECT NVL(MAX("ID"), 0) + 1 INTO next_id FROM "ORDERS";
IF next_id < 5001 THEN
next_id := 5001;
END IF;
EXECUTE IMMEDIATE 'ALTER TABLE "ORDERS" MODIFY ("ID" GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH ' || next_id || '))';
END;
/
CREATE OR REPLACE TRIGGER "TR_ORDERS_UPDATED_AT" BEFORE UPDATE ON "ORDERS" FOR EACH ROW
BEGIN
IF NOT UPDATING('UPDATED_AT') THEN
:NEW."UPDATED_AT" := SYSTIMESTAMP;
END IF;
END;
/
DROP FUNCTION "INTOSQL_CLOB";
DROP FUNCTION "INTOSQL_BLOB";
COMMIT;
EXIT;
修正
- customers の "signed_up" は NULL を許可するようになりました。一部の値が保存できず、NULL になったためです。
- customers の "signed_up" のデフォルト値 0000‑00‑00 は Oracle が受け付ける日付ではないため、列にデフォルト値はありません。
- orders の "status" は NULL を許可するようになりました。一部の値が保存できず、NULL になったためです。
- orders の "updated_at" は更新のたびに現在時刻に変わります。Oracle ではトリガーがこれを行います。
確認が必要
- customers の "signed_up" にある 1 個の値は、0000‑00‑00 のようなゼロ日付または存在しない日付で、Oracle では保存できないため NULL にしました。 その日付に意味がある場合は、ダンプする前にソース側で実際の日付に置き換えてください。
- orders の "shipped_at" にある 1 個の値は、0000‑00‑00 00:00:00 のようなゼロ日付または存在しない日付で、Oracle では保存できないため NULL にしました。 その日付に意味がある場合は、ダンプする前にソース側で実際の日付に置き換えてください。
- orders の "status" にある 1 個の空の値が NULL になりました。Oracle は空文字列を NULL として保存します。 この列を ' と比較しているクエリでは、代わりに IS NULL で比較してください。
ファイルはこのコンピューター上で変換され、アップロードされることはありません。
その他のサンプル:
MySQL から Oracle で変わること
各行はコンバーターが適用するルールです。ルールによってデータが変わったときにレポートに書かれる行も示します。
TINYINT(1), BOOL
すべての値が 0 か 1 なら 0 と 1 の CHECK 付きの NUMBER(1)、それ以外は NUMBER(3)
MySQL の BOOL は -128 から 127 までの任意の数を保持できる TINYINT(1) です。23ai より前の Oracle には boolean 列がないため、0 と 1 の列はチェック制約付きの NUMBER(1) になり、2 や -1 を持つ列は数値を保ちます。
レポートの行: bool_kept_numeric
UNSIGNED integers
範囲に十分な幅の NUMBER、負でないことを確かめる CHECK 付き
Oracle の NUMBER は MySQL のどの幅の整数も保持できます。MySQL と同様にチェック制約で負の値を防ぎます。
ZEROFILL and display widths
削除
ゼロ埋めは数値の表示方法であり、数値の一部ではありません。数値は残ります。ゼロ埋めが必要なら、読み出すときに書式を整えてください。
レポートの行: zerofill_dropped
FLOAT(M,D)
BINARY_FLOAT または BINARY_DOUBLE、桁数指定なし
Oracle のバイナリ浮動小数点数には固定の桁数がありません。保存された値はそのままコピーします。
レポートの行: float_scale_dropped
DECIMAL(p,s)
38 桁までは NUMBER(p,s)、それを超えると VARCHAR2
Oracle の NUMBER は 38 桁まで保持します。それより大きい小数は、すべての桁を正確に保つためテキストで保持します。
レポートの行: decimal_as_text
BIT(1), BIT(n)
NUMBER(1)、63 ビットまでは NUMBER(19)、BIT(64) は NUMBER(20)
ビットフィールドは、ビットが表す数値として保存します。
zero, partial or impossible dates (0000-00-00, 2024-02-30)
NULL
Oracle は実在する暦の日付だけを保存します。MySQL は SQL モードが許せばゼロ日付や存在しない日付を保持しますが、これらは NULL になり、レポートでその数を示します。
レポートの行: invalid_date_null
NOT NULL columns with values that become NULL
NOT NULL を削除
空文字列を含め、値を NULL にする必要があった列は NOT NULL を保てません。保つと読み込みが止まります。
レポートの行: not_null_relaxed
empty strings and empty binary values
NULL
Oracle は空文字列を NULL として保存するため、' だった値は NULL として読み出されます。レポートで列ごとにその数を示します。
レポートの行: empty_string_null
DEFAULT '0000-00-00'
デフォルト値なし
Oracle が保存できないデフォルト値は、架空の日付に置き換えずに省きます。
レポートの行: zero_date_default
TIME
期間を保持できる INTERVAL DAY TO SECOND
Oracle には時刻の型がなく、MySQL の TIME は -838:59:59 から 838:59:59 までの期間です。interval ならすべての値を保持できます。
YEAR
範囲の CHECK 付きの NUMBER(4)
Oracle には年の型がありません。チェック制約で、MySQL が許可するのと同じ値に限定します。
CHAR(n), VARCHAR(n)
VARCHAR2(n CHAR)、文字数で数える
長さは MySQL と同じく文字数で数えます。MySQL は CHAR 値を末尾の空白なしで返し、VARCHAR2 はそのまま保ちます。
VARCHAR(n) and TEXT longer than 4000 bytes
CLOB
VARCHAR2 は既定で 4000 バイトまでなので、それより長いテキストは CLOB になります。値がすべて収まる列は VARCHAR2 のままです。
レポートの行: text_as_lob
DATETIME
TIMESTAMP
DATETIME はタイムゾーンを持たない時計の時刻で、TIMESTAMP と同じです。DATE は Oracle の DATE になり、時刻も持ちますが午前 0 時のままです。
TIMESTAMP
ダンプが示すタイムゾーンでの TIMESTAMP WITH TIME ZONE。示されていなければ UTC
TIMESTAMP はある瞬間を表します。ダンプには書き出したときのタイムゾーンが示されます (mysqldump は UTC で書き出します)。示されていない場合は UTC として読み込み、レポートにその旨を記載します。
レポートの行: timestamp_zone_assumed
ENUM
値の CHECK 付きの VARCHAR2
チェック制約付きのテキストは同じ値を保ちます。
ENUM holding '' (MySQL's error value)
NULL
緩い SQL モードでは、無効な値が ENUM に入ると MySQL は空文字列を保存します。Oracle はこれを NULL として保存し、チェック制約はそれを許可します。レポートでは他の空の値と一緒に数えます。
ENUM holding values outside its list
CHECK なし
リストにない値はチェック制約に違反するため、チェック制約は作成しません。
レポートの行: enum_check_skipped
SET
MySQL が書き出すとおりの VARCHAR2 ('a,b')
Oracle には SET 型がありません。テキストは MySQL が返すものと同じです。
JSON
CLOB
Oracle の JSON 関数はどのバージョンでもテキストから JSON を読み、CLOB ならどんな大きさの値も保持できます。
NUL bytes in text
保持
VARCHAR2 と CLOB は NUL 文字を保持できるため、値はそのままコピーします。
text that isn't valid in its character set
不正なバイトを置換文字に
VARCHAR2 として書き込むには、テキストを文字として読む必要があります。
レポートの行: invalid_utf8_replaced
text decoded twice (ñ)
そのままコピー
ダンプにはまさにこの文字が含まれているため、そのままコピーし、レポートで指摘します。
レポートの行: mojibake_suspected
AUTO_INCREMENT
GENERATED BY DEFAULT ON NULL AS IDENTITY、コピーした ID の後から再開
コピーした ID はそのまま読み込み、カウンターは最大の ID かダンプの AUTO_INCREMENT のうち大きい方の後から続きます。
MyISAM AUTO_INCREMENT on the second column of a key
テーブルに 1 つのカウンター
MyISAM はキーの最初の列のグループごとに採番します。Oracle ではテーブルごとにカウンターは 1 つです。
レポートの行: myisam_group_autoincrement
ON UPDATE CURRENT_TIMESTAMP
BEFORE UPDATE トリガー
更新でその列が設定されなかった場合、トリガーが列を現在時刻にします。
レポートの行: on_update_trigger
generated columns
仮想列
Oracle は生成列を読み取り時にしか計算しません。STORED の列は、同じ値を持つ仮想列になります。
レポートの行: stored_as_virtual
generated columns with functions Oracle lacks
普通の列
Oracle 用に書き換えられない式は、普通の列とレポートの 1 行になります。
レポートの行: generated_not_translated
INVISIBLE columns
INVISIBLE 列
Oracle は MySQL と同様に、SELECT * で非表示の列を返しません。
CHECK constraints
変換して CREATE TABLE 内に記述
CREATE TABLE 内のチェック制約は、各行の読み込み時に検証されます。
CHECK constraints with functions Oracle lacks
作成しない
Oracle 用に書き換えられないチェック制約は省き、レポートに記載します。
レポートの行: check_skipped
CHECK ... NOT ENFORCED
作成しない
MySQL はこれらのチェック制約を適用せずに保持するため、違反する行がある可能性があります。
レポートの行: check_not_enforced
defaults with functions Oracle lacks
デフォルト値なし
Oracle 用に書き換えられないデフォルト値は省き、レポートに記載します。
レポートの行: default_not_translated
keys and indexes on a prefix, c(20)
列の SUBSTR のインデックス
列の同じ先頭部分に対する関数インデックスで同じ行を区別でき、Oracle が全体にはインデックスを作れない CLOB 列にもインデックスを作れます。
レポートの行: prefix_unique
FULLTEXT indexes
作成しない
Oracle Text は独自のインデックス型とクエリで全文検索を構築します。
レポートの行: fulltext_not_created
SPATIAL indexes
作成しない
ジオメトリは WKB のバイト列として保存され、空間インデックスはこれを読めません。
レポートの行: spatial_index_not_created
functional indexes, and indexes on whole CLOB or BLOB columns
作成しない
Oracle はラージオブジェクト全体にはインデックスを作れず、一部の MySQL 関数には Oracle の同等の関数がありません。
レポートの行: index_skipped
foreign keys
データの後に ENABLE NOVALIDATE で作成してから検証し、孤立した行があれば警告
ダンプは FOREIGN_KEY_CHECKS=0 で読み込まれ、MyISAM はチェックを行わないため、親のない行はよくあります。キーは新しい行をすぐにチェックし、最後に検証します。孤立した行があれば、読み込みを止めずにキーを未検証のまま残して警告します。
ON UPDATE CASCADE, SET NULL or SET DEFAULT; ON DELETE SET DEFAULT
削除
Oracle の外部キーが動作するのは削除時だけで、CASCADE か SET NULL のみです。
レポートの行: foreign_key_action_unsupported
foreign keys to columns without a unique key
作成しない
Oracle では参照先の列に主キーか一意制約が必要ですが、InnoDB では不要です。
レポートの行: foreign_key_skipped
table and column names
普通の名前なら大文字、それ以外は書かれたとおり
Oracle は引用符なしで書かれた名前を大文字で保存します。そのため普通の名前は大文字になり、クエリで引用符を省けます。それ以外の名前は大文字小文字を保ち、引用符が必要です。
レポートの行: identifier_renamed
names over 128 bytes
短縮
Oracle 12.2 以降の名前は 128 バイトまでです。
レポートの行: name_shortened
GEOMETRY, POINT, POLYGON...
WKB を持つ BLOB
WKB はどの空間ライブラリでも読める標準の形式です。SDO_GEOMETRY には Oracle Spatial のメタデータが必要です。
レポートの行: geometry_as_blob
INET4, INET6, UUID (MariaDB)
VARCHAR2(39), VARCHAR2(36)
Oracle にはどちらの型もありません。テキストは MariaDB が返すものと同じです。
BINARY, VARBINARY, BLOB
2000 バイトまでは RAW、それ以外は BLOB
バイトはバイトのままです。
PARTITION BY
1 つのテーブル
行は同じです。必要なら Oracle でもう一度テーブルをパーティション分割してください。
レポートの行: partitions_dropped
WITH SYSTEM VERSIONING (MariaDB)
現在の行を持つテーブル
ダンプには現在の行しか含まれません。
レポートの行: system_versioning_dropped
MyISAM, MEMORY and other engines
通常のテーブル
Oracle のテーブルエンジンは 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
WKB を持つ BLOB
MySQL のジオメトリ形式を値から認識し、標準の WKB として保存します。
レポートの行: geometry_inferred
_ci collations
厳密な比較
Oracle は、指定がない限りテキストを厳密に比較します。
レポートの行: 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
CLOB
テキストはどんな値も保持できます。読み込み後に型を変更してください。
レポートの行: unknown_type
values that don't fit their column
NULL
破損したダンプや手書きのダンプには、列が保持できない値が含まれることがあります。それらを NULL にして、残りを読み込みます。
レポートの行: invalid_value_null
unreadable geometries
NULL
ジオメトリでないバイト列は、ジオメトリとして保存できません。
レポートの行: bad_geometry
dumps of several databases
1 つのスキーマ、各テーブルの先頭にデータベース名
スクリプトは実行したユーザーのスキーマに読み込むため、異なるデータベースのテーブルには先頭にデータベース名を付けます。
レポートの行: databases_merged
CREATE SEQUENCE (MariaDB)
到達していた値からの CREATE SEQUENCE
Oracle のシーケンスも同じように動作します。
VECTOR(n) (MariaDB 11.7+)
浮動小数点数の JSON 配列を持つ CLOB
vector 型があるのは Oracle 23ai だけです。JSON 配列はどのバージョンでもすべての浮動小数点数を保ちます。
レポートの行: type_replaced
| MySQL では | Oracle では | レポートの行 |
|---|---|---|
| TINYINT(1), BOOL | すべての値が 0 か 1 なら 0 と 1 の CHECK 付きの NUMBER(1)、それ以外は NUMBER(3)MySQL の BOOL は -128 から 127 までの任意の数を保持できる TINYINT(1) です。23ai より前の Oracle には boolean 列がないため、0 と 1 の列はチェック制約付きの NUMBER(1) になり、2 や -1 を持つ列は数値を保ちます。 | bool_kept_numeric |
| UNSIGNED integers | 範囲に十分な幅の NUMBER、負でないことを確かめる CHECK 付きOracle の NUMBER は MySQL のどの幅の整数も保持できます。MySQL と同様にチェック制約で負の値を防ぎます。 | |
| ZEROFILL and display widths | 削除ゼロ埋めは数値の表示方法であり、数値の一部ではありません。数値は残ります。ゼロ埋めが必要なら、読み出すときに書式を整えてください。 | zerofill_dropped |
| FLOAT(M,D) | BINARY_FLOAT または BINARY_DOUBLE、桁数指定なしOracle のバイナリ浮動小数点数には固定の桁数がありません。保存された値はそのままコピーします。 | float_scale_dropped |
| DECIMAL(p,s) | 38 桁までは NUMBER(p,s)、それを超えると VARCHAR2Oracle の NUMBER は 38 桁まで保持します。それより大きい小数は、すべての桁を正確に保つためテキストで保持します。 | decimal_as_text |
| BIT(1), BIT(n) | NUMBER(1)、63 ビットまでは NUMBER(19)、BIT(64) は NUMBER(20)ビットフィールドは、ビットが表す数値として保存します。 | |
| zero, partial or impossible dates (0000-00-00, 2024-02-30) | NULLOracle は実在する暦の日付だけを保存します。MySQL は SQL モードが許せばゼロ日付や存在しない日付を保持しますが、これらは NULL になり、レポートでその数を示します。 | invalid_date_null |
| NOT NULL columns with values that become NULL | NOT NULL を削除空文字列を含め、値を NULL にする必要があった列は NOT NULL を保てません。保つと読み込みが止まります。 | not_null_relaxed |
| empty strings and empty binary values | NULLOracle は空文字列を NULL として保存するため、' だった値は NULL として読み出されます。レポートで列ごとにその数を示します。 | empty_string_null |
| DEFAULT '0000-00-00' | デフォルト値なしOracle が保存できないデフォルト値は、架空の日付に置き換えずに省きます。 | zero_date_default |
| TIME | 期間を保持できる INTERVAL DAY TO SECONDOracle には時刻の型がなく、MySQL の TIME は -838:59:59 から 838:59:59 までの期間です。interval ならすべての値を保持できます。 | |
| YEAR | 範囲の CHECK 付きの NUMBER(4)Oracle には年の型がありません。チェック制約で、MySQL が許可するのと同じ値に限定します。 | |
| CHAR(n), VARCHAR(n) | VARCHAR2(n CHAR)、文字数で数える長さは MySQL と同じく文字数で数えます。MySQL は CHAR 値を末尾の空白なしで返し、VARCHAR2 はそのまま保ちます。 | |
| VARCHAR(n) and TEXT longer than 4000 bytes | CLOBVARCHAR2 は既定で 4000 バイトまでなので、それより長いテキストは CLOB になります。値がすべて収まる列は VARCHAR2 のままです。 | text_as_lob |
| DATETIME | TIMESTAMPDATETIME はタイムゾーンを持たない時計の時刻で、TIMESTAMP と同じです。DATE は Oracle の DATE になり、時刻も持ちますが午前 0 時のままです。 | |
| TIMESTAMP | ダンプが示すタイムゾーンでの TIMESTAMP WITH TIME ZONE。示されていなければ UTCTIMESTAMP はある瞬間を表します。ダンプには書き出したときのタイムゾーンが示されます (mysqldump は UTC で書き出します)。示されていない場合は UTC として読み込み、レポートにその旨を記載します。 | timestamp_zone_assumed |
| ENUM | 値の CHECK 付きの VARCHAR2チェック制約付きのテキストは同じ値を保ちます。 | |
| ENUM holding '' (MySQL's error value) | NULL緩い SQL モードでは、無効な値が ENUM に入ると MySQL は空文字列を保存します。Oracle はこれを NULL として保存し、チェック制約はそれを許可します。レポートでは他の空の値と一緒に数えます。 | |
| ENUM holding values outside its list | CHECK なしリストにない値はチェック制約に違反するため、チェック制約は作成しません。 | enum_check_skipped |
| SET | MySQL が書き出すとおりの VARCHAR2 ('a,b')Oracle には SET 型がありません。テキストは MySQL が返すものと同じです。 | |
| JSON | CLOBOracle の JSON 関数はどのバージョンでもテキストから JSON を読み、CLOB ならどんな大きさの値も保持できます。 | |
| NUL bytes in text | 保持VARCHAR2 と CLOB は NUL 文字を保持できるため、値はそのままコピーします。 | |
| text that isn't valid in its character set | 不正なバイトを置換文字にVARCHAR2 として書き込むには、テキストを文字として読む必要があります。 | invalid_utf8_replaced |
| text decoded twice (ñ) | そのままコピーダンプにはまさにこの文字が含まれているため、そのままコピーし、レポートで指摘します。 | mojibake_suspected |
| AUTO_INCREMENT | GENERATED BY DEFAULT ON NULL AS IDENTITY、コピーした ID の後から再開コピーした ID はそのまま読み込み、カウンターは最大の ID かダンプの AUTO_INCREMENT のうち大きい方の後から続きます。 | |
| MyISAM AUTO_INCREMENT on the second column of a key | テーブルに 1 つのカウンターMyISAM はキーの最初の列のグループごとに採番します。Oracle ではテーブルごとにカウンターは 1 つです。 | myisam_group_autoincrement |
| ON UPDATE CURRENT_TIMESTAMP | BEFORE UPDATE トリガー更新でその列が設定されなかった場合、トリガーが列を現在時刻にします。 | on_update_trigger |
| generated columns | 仮想列Oracle は生成列を読み取り時にしか計算しません。STORED の列は、同じ値を持つ仮想列になります。 | stored_as_virtual |
| generated columns with functions Oracle lacks | 普通の列Oracle 用に書き換えられない式は、普通の列とレポートの 1 行になります。 | generated_not_translated |
| INVISIBLE columns | INVISIBLE 列Oracle は MySQL と同様に、SELECT * で非表示の列を返しません。 | |
| CHECK constraints | 変換して CREATE TABLE 内に記述CREATE TABLE 内のチェック制約は、各行の読み込み時に検証されます。 | |
| CHECK constraints with functions Oracle lacks | 作成しないOracle 用に書き換えられないチェック制約は省き、レポートに記載します。 | check_skipped |
| CHECK ... NOT ENFORCED | 作成しないMySQL はこれらのチェック制約を適用せずに保持するため、違反する行がある可能性があります。 | check_not_enforced |
| defaults with functions Oracle lacks | デフォルト値なしOracle 用に書き換えられないデフォルト値は省き、レポートに記載します。 | default_not_translated |
| keys and indexes on a prefix, c(20) | 列の SUBSTR のインデックス列の同じ先頭部分に対する関数インデックスで同じ行を区別でき、Oracle が全体にはインデックスを作れない CLOB 列にもインデックスを作れます。 | prefix_unique |
| FULLTEXT indexes | 作成しないOracle Text は独自のインデックス型とクエリで全文検索を構築します。 | fulltext_not_created |
| SPATIAL indexes | 作成しないジオメトリは WKB のバイト列として保存され、空間インデックスはこれを読めません。 | spatial_index_not_created |
| functional indexes, and indexes on whole CLOB or BLOB columns | 作成しないOracle はラージオブジェクト全体にはインデックスを作れず、一部の MySQL 関数には Oracle の同等の関数がありません。 | index_skipped |
| foreign keys | データの後に ENABLE NOVALIDATE で作成してから検証し、孤立した行があれば警告ダンプは FOREIGN_KEY_CHECKS=0 で読み込まれ、MyISAM はチェックを行わないため、親のない行はよくあります。キーは新しい行をすぐにチェックし、最後に検証します。孤立した行があれば、読み込みを止めずにキーを未検証のまま残して警告します。 | |
| ON UPDATE CASCADE, SET NULL or SET DEFAULT; ON DELETE SET DEFAULT | 削除Oracle の外部キーが動作するのは削除時だけで、CASCADE か SET NULL のみです。 | foreign_key_action_unsupported |
| foreign keys to columns without a unique key | 作成しないOracle では参照先の列に主キーか一意制約が必要ですが、InnoDB では不要です。 | foreign_key_skipped |
| table and column names | 普通の名前なら大文字、それ以外は書かれたとおりOracle は引用符なしで書かれた名前を大文字で保存します。そのため普通の名前は大文字になり、クエリで引用符を省けます。それ以外の名前は大文字小文字を保ち、引用符が必要です。 | identifier_renamed |
| names over 128 bytes | 短縮Oracle 12.2 以降の名前は 128 バイトまでです。 | name_shortened |
| GEOMETRY, POINT, POLYGON... | WKB を持つ BLOBWKB はどの空間ライブラリでも読める標準の形式です。SDO_GEOMETRY には Oracle Spatial のメタデータが必要です。 | geometry_as_blob |
| INET4, INET6, UUID (MariaDB) | VARCHAR2(39), VARCHAR2(36)Oracle にはどちらの型もありません。テキストは MariaDB が返すものと同じです。 | |
| BINARY, VARBINARY, BLOB | 2000 バイトまでは RAW、それ以外は BLOBバイトはバイトのままです。 | |
| PARTITION BY | 1 つのテーブル行は同じです。必要なら Oracle でもう一度テーブルをパーティション分割してください。 | partitions_dropped |
| WITH SYSTEM VERSIONING (MariaDB) | 現在の行を持つテーブルダンプには現在の行しか含まれません。 | system_versioning_dropped |
| MyISAM, MEMORY and other engines | 通常のテーブルOracle のテーブルエンジンは 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 | WKB を持つ BLOBMySQL のジオメトリ形式を値から認識し、標準の WKB として保存します。 | geometry_inferred |
| _ci collations | 厳密な比較Oracle は、指定がない限りテキストを厳密に比較します。 | 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 | CLOBテキストはどんな値も保持できます。読み込み後に型を変更してください。 | unknown_type |
| values that don't fit their column | NULL破損したダンプや手書きのダンプには、列が保持できない値が含まれることがあります。それらを NULL にして、残りを読み込みます。 | invalid_value_null |
| unreadable geometries | NULLジオメトリでないバイト列は、ジオメトリとして保存できません。 | bad_geometry |
| dumps of several databases | 1 つのスキーマ、各テーブルの先頭にデータベース名スクリプトは実行したユーザーのスキーマに読み込むため、異なるデータベースのテーブルには先頭にデータベース名を付けます。 | databases_merged |
| CREATE SEQUENCE (MariaDB) | 到達していた値からの CREATE SEQUENCEOracle のシーケンスも同じように動作します。 | |
| VECTOR(n) (MariaDB 11.7+) | 浮動小数点数の JSON 配列を持つ CLOBvector 型があるのは Oracle 23ai だけです。JSON 配列はどのバージョンでもすべての浮動小数点数を保ちます。 | type_replaced |
スクリプトを Oracle に読み込む
スクリプトはテーブルを作成して行をコピーしてから、キー、インデックス、外部キーを追加します。そのため読み込みが速く、最初のエラーで止まります。
NLS_LANG=.AL32UTF8 sqlplus -S -L user@//localhost/mydb @mysql.oracle.sql外部キーは ENABLE NOVALIDATE で追加するため新しい行はすぐにチェックされ、その後に検証します。古い行が存在しない行を参照していれば、途中で失敗する代わりに、どの制約かをスクリプトが示し、その制約は未検証のまま残します。
大きなダンプでは、データベースと同じマシンで SQL*Plus を実行してください。スクリプトは 100 行ごとにコミットします。実行するユーザーには CREATE TABLE、CREATE SEQUENCE、CREATE TRIGGER、CREATE PROCEDURE の権限と、表領域の割り当てが必要です。
MySQL を最適な方法でダンプする
コンバーターはダンプの内容を読み取ります。次のオプションを使うと、より多くのデータがダンプに残ります。
- --default-character-set=utf8mb4 を使うと、絵文字などの 4 バイト文字が残ります。utf8 のダンプでは、コンバーターが読む前にこれらの文字が失われます。
- --hex-blob はバイナリ列を 16 進数で書き出すため、システム間でコピーしても壊れません。
- --routines --triggers --events を使うとこれらのオブジェクトがダンプに含まれ、レポートに一覧できます。
変換されないもの
ビュー、トリガー、ストアドプロシージャ、関数、イベントは、データベースごとに独自の言語で書かれます。黙って削除されることはなく、レポートに名前で一覧されるので、Oracle 用に書き直せます。
MySQL から Oracle への変換に関する質問
ここに答えがない場合は、お問い合わせページからご連絡ください。担当者が返信します。 お問い合わせページ
ダンプはアップロードされますか?
いいえ。コンバーターはブラウザ上で動作し、ダンプをディスクから少しずつ読み込むため、ダンプがコンピューターの外に出ることはありません。デスクトップアプリとコマンドラインも、お使いのコンピューター上で変換します。
ダンプはどのくらいの大きさまで扱えますか?
コンバーターはダンプ全体をメモリに保持しません。ファイルを範囲ごとに 2 回読み、読みながらスクリプトを書き出します。数 GB のダンプも、ブラウザ、デスクトップアプリ、コマンドラインで変換できます。
MariaDB のダンプも読み込めますか?
はい。mariadb-dump や MariaDB 10.3 から 12 のダンプも同じ方法で変換されます。MariaDB の INET6、INET4、UUID 列も対象です。
0000-00-00 の日付はどうなりますか?
Oracle にはゼロ日付がないため、NULL になり、列は NULL を許可します。各列にいくつあったかはレポートに記載されます。空文字列も、Oracle の保存方法どおり NULL になります。
AUTO_INCREMENT の値は保持されますか?
はい。各 AUTO_INCREMENT 列は IDENTITY 列になり、すべての行が ID を保ちます。次の ID は最大の ID の後から、テーブルの AUTO_INCREMENT の方が大きければその後から続きます。
TINYINT(1) は boolean になりますか?
23ai より前の Oracle には boolean 列がありません。値がすべて 0 か 1 の列は、その範囲に限定するチェック制約付きの NUMBER(1) になります。他の数を持つ列はその値を保ち、レポートに理由が書かれます。
ストアドプロシージャやトリガーはどうなりますか?
データベースごとに独自の言語で書かれるため、変換はせず、レポートに名前で一覧します。例外は ON UPDATE CURRENT_TIMESTAMP で、Oracle のトリガーになります。
スクリプトはどの Oracle バージョンで読み込めますか?
Oracle 19c 以降です。すべてのテスト用ダンプを 21c と 23ai で読み込み、問題があれば最初のエラーで止まります。