Конвертация MySQL в SQLite
Перетащите дамп из mysqldump, mariadb-dump, mysqlpump, phpMyAdmin или Adminer в формате .sql или .sql.gz и скачайте скрипт SQLite с теми же таблицами, ключами, индексами и данными. Каждое значение, которое SQLite не может хранить как есть, и каждый объект, который он не переносит, указаны в отчете.
18 строк конвертировано, 8 исправлений, ни одна не отклонена
Таблицы в shop_2024.sqlДамп MySQL 8.0.46 · создан программой mysqldump · utf8mb4
customers8 строк3
7 столбцов id INTEGER not null name VARCHAR(100) not null email VARCHAR(150) not null country VARCHAR(2) not null is_active INTEGER not null signed_up DATE created_at TIMESTAMP not null orders10 строк5
9 столбцов id INTEGER not null customer_id INTEGER not null status TEXT not null total DECIMAL(10,2) not null items INTEGER not null ordered_at DATETIME not null shipped_at DATETIME note VARCHAR(255) updated_at TIMESTAMP not null
-- Written by IntoSQL from a MySQL dump. Load it with: sqlite3 -bail <database> < <file>
PRAGMA foreign_keys = OFF;
PRAGMA synchronous = OFF;
BEGIN;
CREATE TABLE customers ( -- People who bought at least once
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(100) NOT NULL,
email VARCHAR(150) NOT NULL,
country VARCHAR(2) DEFAULT 'US' NOT NULL,
is_active INTEGER DEFAULT 1 NOT NULL,
signed_up DATE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
CONSTRAINT customers_id_check CHECK (id >= 0)
);
CREATE TABLE orders (
id INTEGER PRIMARY KEY AUTOINCREMENT,
customer_id INTEGER NOT NULL,
status TEXT DEFAULT 'pending' NOT NULL,
total DECIMAL(10,2) NOT NULL,
items INTEGER DEFAULT 1 NOT NULL,
ordered_at DATETIME NOT NULL,
shipped_at DATETIME,
note VARCHAR(255),
updated_at TIMESTAMP 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),
CONSTRAINT fk_orders_customer FOREIGN KEY (customer_id) REFERENCES customers (id)
);
INSERT INTO customers (id, name, email, country, is_active, signed_up, created_at) VALUES
(1,'Ana Martínez','ana@example.com','MX',1,'2023-01-15','2023-01-15 10:24:00'),
(2,'Zoë Müller','zoe@example.de','DE',1,'2023-02-03','2023-02-03 08:11:42'),
(3,'José Peña','jose@example.es','ES',0,'2023-03-21','2023-03-21 19:05:17'),
(4,'李雷','lilei@example.cn','CN',1,'2023-05-09','2023-05-09 02:40:00'),
(5,'Noah O''Brien','noah@example.ie','IE',1,NULL,'2023-06-30 14:00:00'),
(6,'Amélie Laurent','amelie@example.fr','FR',1,'2024-01-02','2024-01-02 09:30:00'),
(7,'Ravi Patel','ravi@example.in','IN',0,'2024-02-29','2024-02-29 23:59:59'),
(8,'Sofia Rossi 🌻','sofia@example.it','IT',1,'2024-04-12','2024-04-12 12:12:12');
INSERT INTO orders (id, customer_id, status, total, items, ordered_at, shipped_at, note, updated_at) VALUES
(1,1,'shipped',129.90,3,'2024-03-01 10:00:00','2024-03-02 16:30:00',NULL,'2024-03-02 16:30:00'),
(2,2,'paid',54.00,1,'2024-03-02 11:15:00',NULL,'Gift wrap 🎁','2024-03-02 11:20:00'),
(3,1,'cancelled',12.50,1,'2024-03-03 09:45:00',NULL,'Customer changed their mind','2024-03-03 10: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'),
(5,5,'pending',45.75,2,'2024-03-08 17:20:00',NULL,'Leave at the door; ring twice','2024-03-08 17:20: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'),
(7,8,'paid',76.20,2,'2024-03-11 18:45:00',NULL,NULL,'2024-03-11 18:46:00'),
(8,2,'',19.99,1,'2024-03-12 08:00:00',NULL,'Status lost in an old import','2024-03-12 08:00:00'),
(9,3,'shipped',64.00,2,'2024-03-14 15:30:00',NULL,'Shipping date never recorded','2024-03-15 10:00:00'),
(10,7,'paid',1499.00,1,'2024-03-15 21:05:00',NULL,'C:\Users\ravi\invoice.pdf','2024-03-15 21:05:00');
-- Indexes, triggers and counters, after the rows so each index builds once.
CREATE UNIQUE INDEX customers_uq_email ON customers (email);
CREATE INDEX orders_idx_customer ON orders (customer_id);
CREATE INDEX orders_idx_status_date ON orders (status, ordered_at);
UPDATE sqlite_sequence SET seq = max(seq, 1000) WHERE name = 'customers';
INSERT INTO sqlite_sequence (name, seq) SELECT 'customers', 1000 WHERE NOT EXISTS (SELECT 1 FROM sqlite_sequence WHERE name = 'customers');
UPDATE sqlite_sequence SET seq = max(seq, 5000) WHERE name = 'orders';
INSERT INTO sqlite_sequence (name, seq) SELECT 'orders', 5000 WHERE NOT EXISTS (SELECT 1 FROM sqlite_sequence WHERE name = 'orders');
CREATE TRIGGER orders_updated_at_on_update AFTER UPDATE ON orders FOR EACH ROW WHEN NEW.updated_at IS OLD.updated_at AND (NEW.id IS NOT OLD.id OR NEW.customer_id IS NOT OLD.customer_id OR NEW.status IS NOT OLD.status OR NEW.total IS NOT OLD.total OR NEW.items IS NOT OLD.items OR NEW.ordered_at IS NOT OLD.ordered_at OR NEW.shipped_at IS NOT OLD.shipped_at OR NEW.note IS NOT OLD.note)
BEGIN
UPDATE orders SET updated_at = CURRENT_TIMESTAMP WHERE rowid = NEW.rowid;
END;
COMMIT;
-- Rows whose foreign key finds no parent, if any: the load doesn't stop for them.
PRAGMA foreign_key_check;
Исправления
- Столбец "id" таблицы customers беззнаковый, поэтому он стал INTEGER с проверкой, что значение не отрицательное.
- Столбец "signed_up" таблицы customers теперь допускает NULL: часть его значений нельзя было сохранить, и они записаны как NULL.
- Значение по умолчанию столбца "signed_up" таблицы customers, 0000‑00‑00, не является датой, которую принимает SQLite, поэтому у столбца его нет.
- Столбец "customer_id" таблицы orders беззнаковый, поэтому он стал INTEGER с проверкой, что значение не отрицательное.
- Столбец "id" таблицы orders беззнаковый, поэтому он стал INTEGER с проверкой, что значение не отрицательное.
- Столбец "items" таблицы orders беззнаковый, поэтому он стал INTEGER с проверкой, что значение не отрицательное.
- В 1 строке столбца "status" таблицы orders пустое значение, которое MySQL записывает вместо недопустимых; проверка значений его допускает.
- Столбец "updated_at" таблицы orders получает текущее время при каждом обновлении; в SQLite это делает триггер.
Требует проверки
- В "signed_up" таблицы customers 1 значение - нулевая или невозможная дата, например 0000‑00‑00; SQLite не может их хранить, поэтому записан NULL. Если эти даты что-то значат, замените их в источнике настоящими до создания дампа.
- В "shipped_at" таблицы orders 1 значение - нулевая или невозможная дата, например 0000‑00‑00 00:00:00; SQLite не может их хранить, поэтому записан NULL. Если эти даты что-то значат, замените их в источнике настоящими до создания дампа.
Файл конвертируется на этом компьютере и никуда не загружается.
Другие примеры:
Что меняется при переходе с MySQL на SQLite
Каждая строка - это правило, которое применяет конвертер, и строка отчета, которую он пишет, когда правило что-то меняет в ваших данных.
TINYINT(1), BOOL
INTEGER со значениями как есть
В SQLite нет логического типа; true и false - это целые 1 и 0, поэтому каждое значение сохраняет смысл.
UNSIGNED integers
INTEGER с CHECK на неотрицательность; BIGINT UNSIGNED со значениями больше 2^63-1 становится TEXT
Целые в SQLite 64-битные и знаковые. Проверка не пропускает отрицательные значения, как в MySQL; значения за пределами знакового диапазона хранятся как текст, чтобы ни одна цифра не потерялась.
Строка отчета: unsigned_widened
ZEROFILL and display widths
удаляется
Дополнение нулями - это способ показа числа, а не его часть. Числа сохраняются; если дополнение важно, форматируйте их при чтении.
Строка отчета: zerofill_dropped
FLOAT(M,D)
REAL, без масштаба
У чисел с плавающей точкой в SQLite нет фиксированного масштаба. Записанные значения копируются как есть.
Строка отчета: float_scale_dropped
DECIMAL(p,s)
DECIMAL(p,s) до 15 цифр; дальше TEXT
SQLite хранит в числе около 15 значащих цифр. Более широкие десятичные числа хранятся как текст, чтобы каждая цифра осталась точной.
Строка отчета: decimal_as_text
BIT(1), BIT(n)
INTEGER со значением битов; BIT(64) как цифры в TEXT
Битовое поле хранится как число, которое составляют его биты. Старший бит BIT(64) не помещается в знаковое целое, поэтому его число хранится как текст.
zero, partial or impossible dates (0000-00-00, 2024-02-30)
NULL
Функции дат в SQLite читают только настоящие календарные даты. Они становятся NULL, а отчет их подсчитывает, как и для любой другой базы данных.
Строка отчета: invalid_date_null
NOT NULL columns with values that become NULL
NOT NULL снимается
Столбец, значения которого пришлось заменить на NULL, не может сохранить NOT NULL, иначе загрузка остановится.
Строка отчета: not_null_relaxed
DEFAULT '0000-00-00'
без значения по умолчанию
Значение по умолчанию, которое не является настоящей датой, опускается, а не заменяется выдуманной.
Строка отчета: zero_date_default
TIME
TIME как текст в записи MySQL, включая длительности
SQLite хранит время как текст, поэтому длительности больше суток или меньше нуля сохраняются точно.
YEAR
INTEGER с CHECK диапазона
В SQLite нет типа для года; проверка допускает те же значения, что и MySQL.
CHAR(n), VARCHAR(n)
VARCHAR(n), без ограничения
SQLite сохраняет объявленный тип для инструментов, но не ограничивает длину; значения те же, что возвращает MySQL.
DATETIME
DATETIME как текст ISO 8601
SQLite хранит даты как текст, который читают его функции дат.
TIMESTAMP
TIMESTAMP как текст ISO 8601 в UTC; из пояса, указанного в дампе, или UTC, если он не указан
TIMESTAMP - это момент времени, записанный в UTC. Дампы указывают пояс, в котором он записан (mysqldump пишет UTC); без этого значения читаются как UTC, и отчет это отмечает.
Строка отчета: timestamp_zone_assumed
ENUM
TEXT с CHECK значений
Текст с проверкой хранит те же значения.
ENUM holding '' (MySQL's error value)
пустое значение, которое допускает проверка
MySQL записывает пустую строку, когда недопустимое значение попадает в ENUM в нестрогом режиме SQL. Такие строки сохраняются, и проверка их допускает.
Строка отчета: enum_invalid_value
ENUM holding values outside its list
без CHECK
Значения, которых нет в списке, не прошли бы проверку, поэтому она не создается.
Строка отчета: enum_check_skipped
SET
TEXT в записи MySQL ('a,b')
В SQLite нет массивов; текст тот же, что возвращает MySQL.
JSON
TEXT
Функции JSON в SQLite читают JSON из текста. Столбец, объявленный как JSON, превратил бы "123" в число, поэтому он TEXT.
NUL bytes in text
сохраняется
Текст в SQLite может содержать байт NUL, поэтому значение копируется как есть.
text that isn't valid in its character set
неверные байты заменяются символом замены
Текст в SQLite - это UTF-8; его функции неверно читают байты, которые им не являются.
Строка отчета: invalid_utf8_replaced
text decoded twice (ñ)
копируется как есть
Дамп содержит именно эти символы, поэтому они копируются; отчет на них указывает.
Строка отчета: mojibake_suspected
AUTO_INCREMENT
INTEGER PRIMARY KEY AUTOINCREMENT, счетчик выставлен после скопированных id
SQLite считает первичный ключ из одного целого столбца. AUTOINCREMENT не дает повторно использовать id, как в MySQL, а счетчик продолжается после наибольшего id или после AUTO_INCREMENT дампа, смотря что больше.
AUTO_INCREMENT on part of a key or outside one
INTEGER без счетчика
SQLite считает только столбец, который составляет весь первичный ключ, поэтому столбец сохраняет свои значения, а новым строкам нужны свои.
Строка отчета: identity_without_counter
ON UPDATE CURRENT_TIMESTAMP
триггер AFTER UPDATE
Триггер записывает в столбец текущее время, когда строка меняется, а обновление не задало его, как это делает MySQL.
Строка отчета: on_update_trigger
generated columns
GENERATED ALWAYS AS, VIRTUAL или STORED, как в источнике
SQLite 3.31 и новее вычисляет генерируемые столбцы теми же двумя способами.
generated columns with functions SQLite lacks
обычный столбец
Формула, которую нельзя записать для SQLite, оставляет обычный столбец и строку в отчете.
Строка отчета: generated_not_translated
INVISIBLE columns
обычные столбцы
В SQLite нет невидимых столбцов.
Строка отчета: invisible_column
CHECK constraints
переводится, внутри CREATE TABLE
SQLite принимает проверки только в CREATE TABLE.
CHECK constraints with functions SQLite lacks
не создается
Проверка, которую нельзя записать для SQLite, опускается и попадает в отчет.
Строка отчета: check_skipped
CHECK ... NOT ENFORCED
не создается
MySQL хранит эти проверки, но не применяет их, поэтому строки могут их нарушать.
Строка отчета: check_not_enforced
defaults with functions SQLite lacks
без значения по умолчанию
Значение по умолчанию, которое нельзя записать для SQLite, опускается и попадает в отчет.
Строка отчета: default_not_translated
keys and indexes on a prefix, c(20)
индекс по substr(c, 1, 20)
SQLite индексирует выражения, поэтому индексируется тот же префикс, а уникальный префикс остается уникальным.
Строка отчета: prefix_unique
FULLTEXT indexes
не создается
SQLite ищет по тексту через отдельные таблицы FTS5, которым нужны свои запросы.
Строка отчета: fulltext_not_created
SPATIAL indexes
не создается
В SQLite нет пространственного индекса по столбцу.
Строка отчета: spatial_index_not_created
functional indexes SQLite can't write
не создается
Индекс по выражению, которое нельзя записать для SQLite, опускается и попадает в отчет.
Строка отчета: index_skipped
foreign keys
в CREATE TABLE, загрузка без проверки, затем список через PRAGMA foreign_key_check
SQLite принимает внешние ключи только в CREATE TABLE и проверяет их только при включенном PRAGMA foreign_keys. Строки загружаются без проверки, как из MySQL, а в конце скрипт перечисляет все строки без родителя.
foreign keys to columns without a unique key
не создается
SQLite требует уникальный ключ на столбцах, на которые ссылается внешний ключ; InnoDB - нет.
Строка отчета: foreign_key_skipped
table, index and column names
как в источнике; переименовываются, если отличаются только регистром или имя индекса повторяется
Имена в SQLite не учитывают регистр, а имена индексов делят одно пространство имен на базу данных.
Строка отчета: identifier_renamed
GEOMETRY, POINT, POLYGON...
WKB в BLOB
Стандартный формат well-known binary точно сохраняет каждую геометрию.
Строка отчета: geometry_as_blob
INET4, INET6, UUID (MariaDB)
TEXT
В SQLite нет таких типов; текст тот же, что возвращает MariaDB.
BINARY, VARBINARY, BLOB
BLOB
Байты остаются байтами.
PARTITION BY
одна таблица
Строки те же.
Строка отчета: partitions_dropped
WITH SYSTEM VERSIONING (MariaDB)
таблица с текущими строками
Дамп содержит только текущие строки.
Строка отчета: system_versioning_dropped
MyISAM, MEMORY and other engines
обычная таблица
В SQLite один движок таблиц.
Строка отчета: engine_dropped
dumps of several databases
один файл, имя каждой таблицы начинается с имени ее базы
Файл SQLite - это одна база данных, поэтому имя базы различает таблицы с одинаковыми именами.
Строка отчета: databases_merged
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_as_blob
_ci collations
точное сравнение
SQLite сравнивает текст точно, если не указано иное, а его NOCASE приводит к одному регистру только буквы ASCII.
Строка отчета: 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
TEXT
Тип text вмещает любое значение; измените тип после загрузки.
Строка отчета: unknown_type
values that don't fit their column
NULL
Поврежденный или написанный вручную дамп может содержать значения, которые столбец не вмещает; они становятся NULL, чтобы остальное загрузилось.
Строка отчета: invalid_value_null
unreadable geometries
NULL
Байты, которые не являются геометрией, нельзя сохранить как геометрию.
Строка отчета: bad_geometry
CREATE SEQUENCE (MariaDB)
не создается
В SQLite нет последовательностей.
Строка отчета: sequence_not_converted
VECTOR(n) (MariaDB 11.7+)
TEXT с числами float в виде массива JSON
В SQLite нет векторного типа; массив JSON сохраняет каждое число float.
Строка отчета: type_replaced
| В MySQL | В SQLite | Строка отчета |
|---|---|---|
| TINYINT(1), BOOL | INTEGER со значениями как естьВ SQLite нет логического типа; true и false - это целые 1 и 0, поэтому каждое значение сохраняет смысл. | |
| UNSIGNED integers | INTEGER с CHECK на неотрицательность; BIGINT UNSIGNED со значениями больше 2^63-1 становится TEXTЦелые в SQLite 64-битные и знаковые. Проверка не пропускает отрицательные значения, как в MySQL; значения за пределами знакового диапазона хранятся как текст, чтобы ни одна цифра не потерялась. | unsigned_widened |
| ZEROFILL and display widths | удаляетсяДополнение нулями - это способ показа числа, а не его часть. Числа сохраняются; если дополнение важно, форматируйте их при чтении. | zerofill_dropped |
| FLOAT(M,D) | REAL, без масштабаУ чисел с плавающей точкой в SQLite нет фиксированного масштаба. Записанные значения копируются как есть. | float_scale_dropped |
| DECIMAL(p,s) | DECIMAL(p,s) до 15 цифр; дальше TEXTSQLite хранит в числе около 15 значащих цифр. Более широкие десятичные числа хранятся как текст, чтобы каждая цифра осталась точной. | decimal_as_text |
| BIT(1), BIT(n) | INTEGER со значением битов; BIT(64) как цифры в TEXTБитовое поле хранится как число, которое составляют его биты. Старший бит BIT(64) не помещается в знаковое целое, поэтому его число хранится как текст. | |
| zero, partial or impossible dates (0000-00-00, 2024-02-30) | NULLФункции дат в SQLite читают только настоящие календарные даты. Они становятся NULL, а отчет их подсчитывает, как и для любой другой базы данных. | invalid_date_null |
| NOT NULL columns with values that become NULL | NOT NULL снимаетсяСтолбец, значения которого пришлось заменить на NULL, не может сохранить NOT NULL, иначе загрузка остановится. | not_null_relaxed |
| DEFAULT '0000-00-00' | без значения по умолчаниюЗначение по умолчанию, которое не является настоящей датой, опускается, а не заменяется выдуманной. | zero_date_default |
| TIME | TIME как текст в записи MySQL, включая длительностиSQLite хранит время как текст, поэтому длительности больше суток или меньше нуля сохраняются точно. | |
| YEAR | INTEGER с CHECK диапазонаВ SQLite нет типа для года; проверка допускает те же значения, что и MySQL. | |
| CHAR(n), VARCHAR(n) | VARCHAR(n), без ограниченияSQLite сохраняет объявленный тип для инструментов, но не ограничивает длину; значения те же, что возвращает MySQL. | |
| DATETIME | DATETIME как текст ISO 8601SQLite хранит даты как текст, который читают его функции дат. | |
| TIMESTAMP | TIMESTAMP как текст ISO 8601 в UTC; из пояса, указанного в дампе, или UTC, если он не указанTIMESTAMP - это момент времени, записанный в UTC. Дампы указывают пояс, в котором он записан (mysqldump пишет UTC); без этого значения читаются как UTC, и отчет это отмечает. | timestamp_zone_assumed |
| ENUM | TEXT с CHECK значенийТекст с проверкой хранит те же значения. | |
| ENUM holding '' (MySQL's error value) | пустое значение, которое допускает проверкаMySQL записывает пустую строку, когда недопустимое значение попадает в ENUM в нестрогом режиме SQL. Такие строки сохраняются, и проверка их допускает. | enum_invalid_value |
| ENUM holding values outside its list | без CHECKЗначения, которых нет в списке, не прошли бы проверку, поэтому она не создается. | enum_check_skipped |
| SET | TEXT в записи MySQL ('a,b')В SQLite нет массивов; текст тот же, что возвращает MySQL. | |
| JSON | TEXTФункции JSON в SQLite читают JSON из текста. Столбец, объявленный как JSON, превратил бы "123" в число, поэтому он TEXT. | |
| NUL bytes in text | сохраняетсяТекст в SQLite может содержать байт NUL, поэтому значение копируется как есть. | |
| text that isn't valid in its character set | неверные байты заменяются символом заменыТекст в SQLite - это UTF-8; его функции неверно читают байты, которые им не являются. | invalid_utf8_replaced |
| text decoded twice (ñ) | копируется как естьДамп содержит именно эти символы, поэтому они копируются; отчет на них указывает. | mojibake_suspected |
| AUTO_INCREMENT | INTEGER PRIMARY KEY AUTOINCREMENT, счетчик выставлен после скопированных idSQLite считает первичный ключ из одного целого столбца. AUTOINCREMENT не дает повторно использовать id, как в MySQL, а счетчик продолжается после наибольшего id или после AUTO_INCREMENT дампа, смотря что больше. | |
| AUTO_INCREMENT on part of a key or outside one | INTEGER без счетчикаSQLite считает только столбец, который составляет весь первичный ключ, поэтому столбец сохраняет свои значения, а новым строкам нужны свои. | identity_without_counter |
| ON UPDATE CURRENT_TIMESTAMP | триггер AFTER UPDATEТриггер записывает в столбец текущее время, когда строка меняется, а обновление не задало его, как это делает MySQL. | on_update_trigger |
| generated columns | GENERATED ALWAYS AS, VIRTUAL или STORED, как в источникеSQLite 3.31 и новее вычисляет генерируемые столбцы теми же двумя способами. | |
| generated columns with functions SQLite lacks | обычный столбецФормула, которую нельзя записать для SQLite, оставляет обычный столбец и строку в отчете. | generated_not_translated |
| INVISIBLE columns | обычные столбцыВ SQLite нет невидимых столбцов. | invisible_column |
| CHECK constraints | переводится, внутри CREATE TABLESQLite принимает проверки только в CREATE TABLE. | |
| CHECK constraints with functions SQLite lacks | не создаетсяПроверка, которую нельзя записать для SQLite, опускается и попадает в отчет. | check_skipped |
| CHECK ... NOT ENFORCED | не создаетсяMySQL хранит эти проверки, но не применяет их, поэтому строки могут их нарушать. | check_not_enforced |
| defaults with functions SQLite lacks | без значения по умолчаниюЗначение по умолчанию, которое нельзя записать для SQLite, опускается и попадает в отчет. | default_not_translated |
| keys and indexes on a prefix, c(20) | индекс по substr(c, 1, 20)SQLite индексирует выражения, поэтому индексируется тот же префикс, а уникальный префикс остается уникальным. | prefix_unique |
| FULLTEXT indexes | не создаетсяSQLite ищет по тексту через отдельные таблицы FTS5, которым нужны свои запросы. | fulltext_not_created |
| SPATIAL indexes | не создаетсяВ SQLite нет пространственного индекса по столбцу. | spatial_index_not_created |
| functional indexes SQLite can't write | не создаетсяИндекс по выражению, которое нельзя записать для SQLite, опускается и попадает в отчет. | index_skipped |
| foreign keys | в CREATE TABLE, загрузка без проверки, затем список через PRAGMA foreign_key_checkSQLite принимает внешние ключи только в CREATE TABLE и проверяет их только при включенном PRAGMA foreign_keys. Строки загружаются без проверки, как из MySQL, а в конце скрипт перечисляет все строки без родителя. | |
| foreign keys to columns without a unique key | не создаетсяSQLite требует уникальный ключ на столбцах, на которые ссылается внешний ключ; InnoDB - нет. | foreign_key_skipped |
| table, index and column names | как в источнике; переименовываются, если отличаются только регистром или имя индекса повторяетсяИмена в SQLite не учитывают регистр, а имена индексов делят одно пространство имен на базу данных. | identifier_renamed |
| GEOMETRY, POINT, POLYGON... | WKB в BLOBСтандартный формат well-known binary точно сохраняет каждую геометрию. | geometry_as_blob |
| INET4, INET6, UUID (MariaDB) | TEXTВ SQLite нет таких типов; текст тот же, что возвращает MariaDB. | |
| BINARY, VARBINARY, BLOB | BLOBБайты остаются байтами. | |
| PARTITION BY | одна таблицаСтроки те же. | partitions_dropped |
| WITH SYSTEM VERSIONING (MariaDB) | таблица с текущими строкамиДамп содержит только текущие строки. | system_versioning_dropped |
| MyISAM, MEMORY and other engines | обычная таблицаВ SQLite один движок таблиц. | engine_dropped |
| dumps of several databases | один файл, имя каждой таблицы начинается с имени ее базыФайл SQLite - это одна база данных, поэтому имя базы различает таблицы с одинаковыми именами. | databases_merged |
| 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_as_blob |
| _ci collations | точное сравнениеSQLite сравнивает текст точно, если не указано иное, а его NOCASE приводит к одному регистру только буквы ASCII. | 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 | TEXTТип text вмещает любое значение; измените тип после загрузки. | unknown_type |
| values that don't fit their column | NULLПоврежденный или написанный вручную дамп может содержать значения, которые столбец не вмещает; они становятся NULL, чтобы остальное загрузилось. | invalid_value_null |
| unreadable geometries | NULLБайты, которые не являются геометрией, нельзя сохранить как геометрию. | bad_geometry |
| CREATE SEQUENCE (MariaDB) | не создаетсяВ SQLite нет последовательностей. | sequence_not_converted |
| VECTOR(n) (MariaDB 11.7+) | TEXT с числами float в виде массива JSONВ SQLite нет векторного типа; массив JSON сохраняет каждое число float. | type_replaced |
Загрузите скрипт в SQLite
Скрипт создает таблицы, копирует строки, затем добавляет ключи, индексы и внешние ключи, поэтому загрузка идет быстро и останавливается на первой ошибке.
sqlite3 -bail mydb.sqlite < mysql.sqlite.sqlВнешние ключи объявляются в каждой таблице, а строки загружаются с отключенной проверкой внешних ключей. Затем скрипт перечисляет все строки, которые ссылаются на несуществующие строки, а не прерывается на полпути.
Большой дамп загружайте в новый файл на локальном диске. Скрипт загружает все в одной транзакции с отключенной синхронизацией, поэтому работает со скоростью диска, а прерванная загрузка не оставляет неполных таблиц.
Командная строка загружает файл прямо в базу SQLite, без написания скрипта. Это бесплатно.
Как создать дамп MySQL для лучшего результата
Конвертер читает то, что есть в дампе. Эти параметры сохраняют в нем больше ваших данных:
- --default-character-set=utf8mb4 сохраняет эмодзи и другие 4-байтовые символы, которые дамп в utf8 теряет еще до конвертера.
- --hex-blob записывает двоичные столбцы в шестнадцатеричном виде, который не портится при копировании между системами.
- --routines --triggers --events добавляют эти объекты в дамп, чтобы отчет мог их перечислить.
Что не конвертируется
Представления, триггеры, хранимые процедуры, функции и события написаны на собственном языке каждой базы данных. Они перечислены в отчете по имени и никогда не удаляются молча, чтобы вы могли переписать их для SQLite.
Вопросы о MySQL в SQLite
Нет ответа на ваш вопрос? Напишите нам через страницу контактов, и вам ответит человек. Страница контактов
Мой дамп загружается на сервер?
Нет. Конвертер работает в вашем браузере и читает дамп с диска по частям, поэтому он никогда не покидает ваш компьютер. Приложение для компьютера и командная строка тоже конвертируют на вашем компьютере.
Насколько большим может быть дамп?
Конвертер никогда не держит весь дамп в памяти: он читает файл дважды, по диапазонам, и пишет скрипт по ходу чтения. Дампы в несколько гигабайт конвертируются в браузере, в приложении для компьютера и в командной строке.
Читает ли он дампы MariaDB?
Да. Дампы из mariadb-dump и из MariaDB с 10.3 по 12 конвертируются так же, включая столбцы INET6, INET4 и UUID в MariaDB.
Что происходит с датами 0000-00-00?
Они становятся NULL: SQLite сохранил бы текст, но ничто не читает 0000-00-00 как дату. Отчет показывает, сколько их было в каждом столбце.
Сохраняются ли значения AUTO_INCREMENT?
Да. Столбец AUTO_INCREMENT, который составляет весь первичный ключ таблицы, становится INTEGER PRIMARY KEY AUTOINCREMENT, каждая строка сохраняет свой id, а следующий id идет после наибольшего. Любой другой столбец AUTO_INCREMENT сохраняет значения без счетчика, и отчет это отмечает.
Становится ли TINYINT(1) типом boolean?
Нет. В SQLite нет логического типа, поэтому TINYINT(1) становится INTEGER, и каждое значение остается как есть.
А хранимые процедуры и триггеры?
Они перечислены в отчете по имени и не конвертируются, потому что каждая база данных пишет их на своем языке. Исключение - ON UPDATE CURRENT_TIMESTAMP: он становится триггером SQLite.
На каких версиях SQLite загружается скрипт?
SQLite 3.31 и новее. Каждый тестовый дамп загружается на 3.31 и 3.54 и останавливается на первой ошибке, если что-то пойдет не так.