Перейти к содержимому
Главная страница IntoSQL

Конвертация MySQL в Oracle

Перетащите дамп из mysqldump, mariadb-dump, mysqlpump, phpMyAdmin или Adminer в формате .sql или .sql.gz и скачайте скрипт Oracle с теми же таблицами, ключами, индексами и данными. Каждое значение, которое Oracle не может хранить как есть, и каждый объект, который он не переносит, указаны в отчете.

Ваш файл
sqlshop_2024.sqlПример файла, 5,1 кБ
Ваша база данных

18 строк конвертировано, 4 исправления, ни одна не отклонена

Показать

Таблицы в shop_2024.sqlДамп MySQL 8.0.46 · создан программой mysqldump · utf8mb4

  • customersзаписана как CUSTOMERS8 строк2
    7 столбцов
    IDNUMBER(10) not null
    NAMEVARCHAR2(100 CHAR) not null
    EMAILVARCHAR2(150 CHAR) not null
    COUNTRYVARCHAR2(2 CHAR) not null
    IS_ACTIVENUMBER(1) not null
    SIGNED_UPDATE
    CREATED_ATTIMESTAMP(0) WITH TIME ZONE not null
  • ordersзаписана как ORDERS10 строк2
    9 столбцов
    IDNUMBER(10) not null
    CUSTOMER_IDNUMBER(10) not null
    STATUSVARCHAR2(9 CHAR)
    TOTALNUMBER(10,2) not null
    ITEMSNUMBER(5) not null
    ORDERED_ATTIMESTAMP(0) not null
    SHIPPED_ATTIMESTAMP(0)
    NOTEVARCHAR2(255 CHAR)
    UPDATED_ATTIMESTAMP(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;

Исправления

  1. Столбец "signed_up" таблицы customers теперь допускает NULL: часть его значений нельзя было сохранить, и они записаны как NULL.
  2. Значение по умолчанию столбца "signed_up" таблицы customers, 0000‑00‑00, не является датой, которую принимает Oracle, поэтому у столбца его нет.
  3. Столбец "status" таблицы orders теперь допускает NULL: часть его значений нельзя было сохранить, и они записаны как NULL.
  4. Столбец "updated_at" таблицы orders получает текущее время при каждом обновлении; в Oracle это делает триггер.

Требует проверки

  • В "signed_up" таблицы customers 1 значение - нулевая или невозможная дата, например 0000‑00‑00; Oracle не может их хранить, поэтому записан NULL. Если эти даты что-то значат, замените их в источнике настоящими до создания дампа.
  • В "shipped_at" таблицы orders 1 значение - нулевая или невозможная дата, например 0000‑00‑00 00:00:00; Oracle не может их хранить, поэтому записан NULL. Если эти даты что-то значат, замените их в источнике настоящими до создания дампа.
  • В "status" таблицы orders 1 пустое значение стало NULL; Oracle хранит пустую строку как NULL. Где запросы сравнивают этот столбец с ', сравнивайте с IS NULL.

Файл конвертируется на этом компьютере и никуда не загружается.

Другие примеры:

Что меняется при переходе с MySQL на Oracle

Каждая строка - это правило, которое применяет конвертер, и строка отчета, которую он пишет, когда правило что-то меняет в ваших данных.

  • TINYINT(1), BOOL

    NUMBER(1) с CHECK на 0 и 1, если каждое значение 0 или 1, иначе NUMBER(3)

    BOOL в MySQL - это TINYINT(1), который может хранить любое число от -128 до 127. В Oracle до 23ai нет логического столбца, поэтому столбец из 0 и 1 становится NUMBER(1) с проверкой; столбец с 2 или -1 сохраняет свои числа.

    Строка отчета: bool_kept_numeric

  • UNSIGNED integers

    NUMBER достаточной ширины для диапазона, с CHECK на неотрицательность

    NUMBER в Oracle вмещает любое целое тех размеров, что есть в MySQL; проверка не пропускает отрицательные значения, как в MySQL.

  • ZEROFILL and display widths

    удаляется

    Дополнение нулями - это способ показа числа, а не его часть. Числа сохраняются; если дополнение важно, форматируйте их при чтении.

    Строка отчета: zerofill_dropped

  • FLOAT(M,D)

    BINARY_FLOAT или BINARY_DOUBLE, без масштаба

    У двоичных чисел с плавающей точкой в Oracle нет фиксированного масштаба. Записанные значения копируются как есть.

    Строка отчета: float_scale_dropped

  • DECIMAL(p,s)

    NUMBER(p,s) до 38 цифр; дальше VARCHAR2

    NUMBER в Oracle вмещает 38 цифр. Более широкие десятичные числа хранятся как текст, чтобы каждая цифра осталась точной.

    Строка отчета: decimal_as_text

  • BIT(1), BIT(n)

    NUMBER(1), NUMBER(19) до 63 бит, NUMBER(20) для BIT(64)

    Битовые поля хранятся как число, которое составляют их биты.

  • 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 нет типа для времени суток, а TIME в MySQL - это длительность от -838:59:59 до 838:59:59; интервал вмещает любое значение.

  • YEAR

    NUMBER(4) с CHECK диапазона

    В 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 становится DATE в Oracle, который хранит и время суток, оно остается полночью.

  • TIMESTAMP

    TIMESTAMP WITH TIME ZONE в поясе, указанном в дампе, или UTC, если он не указан

    TIMESTAMP - это момент времени. Дампы указывают пояс, в котором он записан (mysqldump пишет UTC); без этого значения читаются как UTC, и отчет это отмечает.

    Строка отчета: timestamp_zone_assumed

  • ENUM

    VARCHAR2 с CHECK значений

    Текст с проверкой хранит те же значения.

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

    NULL

    MySQL записывает пустую строку, когда недопустимое значение попадает в ENUM в нестрогом режиме SQL. Oracle хранит ее как NULL, что проверка допускает, а отчет учитывает ее вместе с другими пустыми значениями.

  • ENUM holding values outside its list

    без CHECK

    Значения, которых нет в списке, не прошли бы проверку, поэтому она не создается.

    Строка отчета: enum_check_skipped

  • SET

    VARCHAR2 в записи MySQL ('a,b')

    В Oracle нет типа множества; текст тот же, что возвращает MySQL.

  • JSON

    CLOB

    Функции JSON в Oracle читают 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 загружаются как есть, а счетчик продолжается после наибольшего из них или после AUTO_INCREMENT дампа, смотря что больше.

  • MyISAM AUTO_INCREMENT on the second column of a key

    один счетчик на таблицу

    MyISAM считает отдельно для каждой группы первого столбца ключа; в Oracle один счетчик на таблицу.

    Строка отчета: 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, оставляет обычный столбец и строку в отчете.

    Строка отчета: generated_not_translated

  • INVISIBLE columns

    столбцы INVISIBLE

    Oracle скрывает невидимые столбцы от SELECT *, как MySQL.

  • CHECK constraints

    переводится, внутри 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 столбца

    Функциональный индекс по тому же началу столбца различает те же строки и индексирует столбцы CLOB, которые Oracle не индексирует целиком.

    Строка отчета: 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...

    BLOB с WKB

    WKB - стандартный формат, который читает любая пространственная библиотека; SDO_GEOMETRY нужны метаданные Oracle Spatial.

    Строка отчета: geometry_as_blob

  • INET4, INET6, UUID (MariaDB)

    VARCHAR2(39), VARCHAR2(36)

    В Oracle нет ни одного из этих типов; текст тот же, что возвращает MariaDB.

  • BINARY, VARBINARY, BLOB

    RAW до 2000 байт, иначе BLOB

    Байты остаются байтами.

  • PARTITION BY

    одна таблица

    Строки те же; при необходимости секционируйте таблицу заново в Oracle.

    Строка отчета: partitions_dropped

  • WITH SYSTEM VERSIONING (MariaDB)

    таблица с текущими строками

    Дамп содержит только текущие строки.

    Строка отчета: system_versioning_dropped

  • MyISAM, MEMORY and other engines

    обычная таблица

    В Oracle один движок таблиц.

    Строка отчета: 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

    BLOB с WKB

    Формат геометрии MySQL распознается по значениям и сохраняется как стандартный WKB.

    Строка отчета: geometry_inferred

  • _ci collations

    точное сравнение

    Oracle сравнивает текст точно, если не указано иное.

    Строка отчета: case_insensitive_collation

  • SET NAMES utf8 from utf8mb4 tables

    конвертируется с предупреждением

    mysqldump из MySQL 5.x по умолчанию пишет 3-байтовую utf8 и заменяет каждый эмодзи вопросительным знаком еще до того, как файл увидит какой-либо конвертер.

    Строка отчета: dump_lost_four_byte_chars

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

    читается как Latin-1 (Windows-1252)

    latin1 в MySQL - это 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

    обычные строки

    В дампе одна строка на ключ, поэтому строки те же.

    Строка отчета: replace_as_insert

  • types IntoSQL doesn't know

    CLOB

    Тип text вмещает любое значение; измените тип после загрузки.

    Строка отчета: unknown_type

  • values that don't fit their column

    NULL

    Поврежденный или написанный вручную дамп может содержать значения, которые столбец не вмещает; они становятся NULL, чтобы остальное загрузилось.

    Строка отчета: invalid_value_null

  • unreadable geometries

    NULL

    Байты, которые не являются геометрией, нельзя сохранить как геометрию.

    Строка отчета: bad_geometry

  • dumps of several databases

    одна схема, имя каждой таблицы начинается с имени ее базы

    Скрипт загружается в схему пользователя, который его запускает, поэтому таблицы из разных баз данных получают в начале имя своей базы.

    Строка отчета: databases_merged

  • CREATE SEQUENCE (MariaDB)

    CREATE SEQUENCE с достигнутым значением

    Последовательности в Oracle работают так же.

  • VECTOR(n) (MariaDB 11.7+)

    CLOB с числами float в виде массива JSON

    Векторный тип есть только в Oracle 23ai; массив JSON сохраняет каждое число float в любой версии.

    Строка отчета: type_replaced

В MySQLВ OracleСтрока отчета
TINYINT(1), BOOLNUMBER(1) с CHECK на 0 и 1, если каждое значение 0 или 1, иначе NUMBER(3)BOOL в MySQL - это TINYINT(1), который может хранить любое число от -128 до 127. В Oracle до 23ai нет логического столбца, поэтому столбец из 0 и 1 становится NUMBER(1) с проверкой; столбец с 2 или -1 сохраняет свои числа.bool_kept_numeric
UNSIGNED integersNUMBER достаточной ширины для диапазона, с CHECK на неотрицательностьNUMBER в Oracle вмещает любое целое тех размеров, что есть в MySQL; проверка не пропускает отрицательные значения, как в MySQL.
ZEROFILL and display widthsудаляетсяДополнение нулями - это способ показа числа, а не его часть. Числа сохраняются; если дополнение важно, форматируйте их при чтении.zerofill_dropped
FLOAT(M,D)BINARY_FLOAT или BINARY_DOUBLE, без масштабаУ двоичных чисел с плавающей точкой в Oracle нет фиксированного масштаба. Записанные значения копируются как есть.float_scale_dropped
DECIMAL(p,s)NUMBER(p,s) до 38 цифр; дальше VARCHAR2NUMBER в Oracle вмещает 38 цифр. Более широкие десятичные числа хранятся как текст, чтобы каждая цифра осталась точной.decimal_as_text
BIT(1), BIT(n)NUMBER(1), NUMBER(19) до 63 бит, NUMBER(20) для BIT(64)Битовые поля хранятся как число, которое составляют их биты.
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 NULLNOT NULL снимаетсяСтолбец, значения которого пришлось заменить на NULL, включая пустые строки, не может сохранить NOT NULL, иначе загрузка остановится.not_null_relaxed
empty strings and empty binary valuesNULLOracle хранит пустую строку как NULL, поэтому значение ' читается обратно как NULL. Отчет подсчитывает их по столбцам.empty_string_null
DEFAULT '0000-00-00'без значения по умолчаниюЗначение по умолчанию, которое Oracle не может хранить, опускается, а не заменяется выдуманной датой.zero_date_default
TIMEINTERVAL DAY TO SECOND, который вмещает длительностиВ Oracle нет типа для времени суток, а TIME в MySQL - это длительность от -838:59:59 до 838:59:59; интервал вмещает любое значение.
YEARNUMBER(4) с CHECK диапазонаВ Oracle нет типа для года; проверка допускает те же значения, что и MySQL.
CHAR(n), VARCHAR(n)VARCHAR2(n CHAR), длина в символахДлина считается в символах, как в MySQL, а MySQL возвращает значения CHAR без пробелов в конце, и VARCHAR2 хранит их так же.
VARCHAR(n) and TEXT longer than 4000 bytesCLOBVARCHAR2 по умолчанию вмещает 4000 байт, поэтому более длинный текст становится CLOB; столбец, все значения которого помещаются, остается VARCHAR2.text_as_lob
DATETIMETIMESTAMPDATETIME - это показание часов без часового пояса, как TIMESTAMP. DATE становится DATE в Oracle, который хранит и время суток, оно остается полночью.
TIMESTAMPTIMESTAMP WITH TIME ZONE в поясе, указанном в дампе, или UTC, если он не указанTIMESTAMP - это момент времени. Дампы указывают пояс, в котором он записан (mysqldump пишет UTC); без этого значения читаются как UTC, и отчет это отмечает.timestamp_zone_assumed
ENUMVARCHAR2 с CHECK значенийТекст с проверкой хранит те же значения.
ENUM holding '' (MySQL's error value)NULLMySQL записывает пустую строку, когда недопустимое значение попадает в ENUM в нестрогом режиме SQL. Oracle хранит ее как NULL, что проверка допускает, а отчет учитывает ее вместе с другими пустыми значениями.
ENUM holding values outside its listбез CHECKЗначения, которых нет в списке, не прошли бы проверку, поэтому она не создается.enum_check_skipped
SETVARCHAR2 в записи MySQL ('a,b')В Oracle нет типа множества; текст тот же, что возвращает MySQL.
JSONCLOBФункции JSON в Oracle читают 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_INCREMENTGENERATED BY DEFAULT ON NULL AS IDENTITY, перезапуск после скопированных idСкопированные id загружаются как есть, а счетчик продолжается после наибольшего из них или после AUTO_INCREMENT дампа, смотря что больше.
MyISAM AUTO_INCREMENT on the second column of a keyодин счетчик на таблицуMyISAM считает отдельно для каждой группы первого столбца ключа; в Oracle один счетчик на таблицу.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, оставляет обычный столбец и строку в отчете.generated_not_translated
INVISIBLE columnsстолбцы INVISIBLEOracle скрывает невидимые столбцы от SELECT *, как MySQL.
CHECK constraintsпереводится, внутри 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 столбцаФункциональный индекс по тому же началу столбца различает те же строки и индексирует столбцы CLOB, которые Oracle не индексирует целиком.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...BLOB с WKBWKB - стандартный формат, который читает любая пространственная библиотека; SDO_GEOMETRY нужны метаданные Oracle Spatial.geometry_as_blob
INET4, INET6, UUID (MariaDB)VARCHAR2(39), VARCHAR2(36)В Oracle нет ни одного из этих типов; текст тот же, что возвращает MariaDB.
BINARY, VARBINARY, BLOBRAW до 2000 байт, иначе BLOBБайты остаются байтами.
PARTITION BYодна таблицаСтроки те же; при необходимости секционируйте таблицу заново в Oracle.partitions_dropped
WITH SYSTEM VERSIONING (MariaDB)таблица с текущими строкамиДамп содержит только текущие строки.system_versioning_dropped
MyISAM, MEMORY and other enginesобычная таблицаВ Oracle один движок таблиц.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 TABLEBLOB с WKBФормат геометрии MySQL распознается по значениям и сохраняется как стандартный WKB.geometry_inferred
_ci collationsточное сравнениеOracle сравнивает текст точно, если не указано иное.case_insensitive_collation
SET NAMES utf8 from utf8mb4 tablesконвертируется с предупреждениемmysqldump из MySQL 5.x по умолчанию пишет 3-байтовую utf8 и заменяет каждый эмодзи вопросительным знаком еще до того, как файл увидит какой-либо конвертер.dump_lost_four_byte_chars
dumps without SET NAMES whose text isn't UTF-8читается как Latin-1 (Windows-1252)latin1 в MySQL - это 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 rowsNULLКонвертер, который не запускает базу данных, не может их вычислить.expression_value
DEFAULT in VALUESзначение столбца по умолчаниюЛитеральное значение по умолчанию копируется в строку.default_keyword_filled
DEFAULT in VALUES without a literal defaultNULLКопировать нечего.default_keyword_null
REPLACE and INSERT IGNOREобычные строкиВ дампе одна строка на ключ, поэтому строки те же.replace_as_insert
types IntoSQL doesn't knowCLOBТип text вмещает любое значение; измените тип после загрузки.unknown_type
values that don't fit their columnNULLПоврежденный или написанный вручную дамп может содержать значения, которые столбец не вмещает; они становятся NULL, чтобы остальное загрузилось.invalid_value_null
unreadable geometriesNULLБайты, которые не являются геометрией, нельзя сохранить как геометрию.bad_geometry
dumps of several databasesодна схема, имя каждой таблицы начинается с имени ее базыСкрипт загружается в схему пользователя, который его запускает, поэтому таблицы из разных баз данных получают в начале имя своей базы.databases_merged
CREATE SEQUENCE (MariaDB)CREATE SEQUENCE с достигнутым значениемПоследовательности в Oracle работают так же.
VECTOR(n) (MariaDB 11.7+)CLOB с числами float в виде массива JSONВекторный тип есть только в Oracle 23ai; массив JSON сохраняет каждое число float в любой версии.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 записывает двоичные столбцы в шестнадцатеричном виде, который не портится при копировании между системами.
  • --routines --triggers --events добавляют эти объекты в дамп, чтобы отчет мог их перечислить.

Что не конвертируется

Представления, триггеры, хранимые процедуры, функции и события написаны на собственном языке каждой базы данных. Они перечислены в отчете по имени и никогда не удаляются молча, чтобы вы могли переписать их для Oracle.

Вопросы о MySQL в Oracle

Нет ответа на ваш вопрос? Напишите нам через страницу контактов, и вам ответит человек. Страница контактов

Мой дамп загружается на сервер?

Нет. Конвертер работает в вашем браузере и читает дамп с диска по частям, поэтому он никогда не покидает ваш компьютер. Приложение для компьютера и командная строка тоже конвертируют на вашем компьютере.

Насколько большим может быть дамп?

Конвертер никогда не держит весь дамп в памяти: он читает файл дважды, по диапазонам, и пишет скрипт по ходу чтения. Дампы в несколько гигабайт конвертируются в браузере, в приложении для компьютера и в командной строке.

Читает ли он дампы MariaDB?

Да. Дампы из mariadb-dump и из MariaDB с 10.3 по 12 конвертируются так же, включая столбцы INET6, INET4 и UUID в MariaDB.

Что происходит с датами 0000-00-00?

В Oracle нет нулевой даты, поэтому они становятся NULL, а столбец допускает NULL. Отчет показывает, сколько их было в каждом столбце. Пустые строки тоже становятся NULL, так их хранит Oracle.

Сохраняются ли значения AUTO_INCREMENT?

Да. Каждый столбец AUTO_INCREMENT становится столбцом identity, каждая строка сохраняет свой id, а следующий id идет после наибольшего или после AUTO_INCREMENT таблицы, если он больше.

Становится ли TINYINT(1) типом boolean?

В Oracle до 23ai нет логического столбца. Столбец, все значения которого 0 или 1, становится NUMBER(1) с проверкой, которая это сохраняет; столбец с другими числами их сохраняет, а отчет объясняет почему.

А хранимые процедуры и триггеры?

Они перечислены в отчете по имени и не конвертируются, потому что каждая база данных пишет их на своем языке. Исключение - ON UPDATE CURRENT_TIMESTAMP: он становится триггером Oracle.

На каких версиях Oracle загружается скрипт?

Oracle 19c и новее. Каждый тестовый дамп загружается на 21c и 23ai и останавливается на первой ошибке, если что-то пойдет не так.