Перенесите базу SQLite на более старую или новую версию SQLite
Перетащите файл базы данных SQLite (.db, .sqlite, .sqlite3) или SQL, который пишет .dump в sqlite3, и скачайте скрипт, который загружается на SQLite 3.31 и новее. Каждый столбец сохраняет объявленный тип и collation, STRICT опускается, чтобы старые версии принимали таблицы, и каждое изменение указано в отчете.
18 строк конвертировано, без исправлений, ни одна не отклонена
Таблицы в shop_2024_sqlite.sqlДамп SQLite · создан программой sqlite3 · utf-8
customers8 строк
7 столбцов id INTEGER not null name TEXT not null email TEXT not null country TEXT not null is_active INTEGER not null signed_up DATE created_at DATETIME not null orders10 строк
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 TEXT receipt BLOB
Не конвертировано
- Представление order_totals
- Триггер orders_shipped
Каждая база данных пишет их на своем языке. Перепишите их для SQLite.
-- Written by IntoSQL from a SQLite dump. Load it with: sqlite3 -bail <database> < <file>
PRAGMA foreign_keys = OFF;
PRAGMA synchronous = OFF;
BEGIN;
CREATE TABLE customers (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT COLLATE NOCASE NOT NULL,
country TEXT DEFAULT 'US' NOT NULL,
is_active INTEGER DEFAULT 1 NOT NULL,
signed_up DATE,
created_at DATETIME DEFAULT (datetime('now', 'localtime')) NOT NULL,
CONSTRAINT customers_is_active_check CHECK (is_active IN (0, 1)),
CONSTRAINT customers_check1 CHECK (length(country) = 2)
);
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 TEXT,
receipt BLOB,
CONSTRAINT orders_check1 CHECK (status IN ('pending', 'paid', 'shipped', 'cancelled')),
CONSTRAINT orders_fkey FOREIGN KEY (customer_id) REFERENCES customers (id) ON DELETE CASCADE
);
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');
INSERT INTO customers (id, name, email, country, is_active, signed_up, created_at) VALUES
(2,'Zoë Müller','zoe@example.de','DE',1,'2023-02-03','2023-02-03 08:11:42');
INSERT INTO customers (id, name, email, country, is_active, signed_up, created_at) VALUES
(3,'José Peña','jose@example.es','ES',0,'2023-03-21','2023-03-21 19:05:17');
INSERT INTO customers (id, name, email, country, is_active, signed_up, created_at) VALUES
(4,'李雷','lilei@example.cn','CN',1,'2023-05-09','2023-05-09 02:40: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,'2023-06-30 14: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,'2024-01-02','2024-01-02 09:30:00');
INSERT INTO customers (id, name, email, country, is_active, signed_up, created_at) VALUES
(7,'Ravi Patel','ravi@example.in','IN',0,'2024-02-29','2024-02-29 23:59:59');
INSERT INTO customers (id, name, email, country, is_active, signed_up, created_at) VALUES
(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, receipt) VALUES
(1,1,'shipped',129.9,3,'2024-03-01 10:00:00','2024-03-02 16:30:00',NULL,NULL);
INSERT INTO orders (id, customer_id, status, total, items, ordered_at, shipped_at, note, receipt) VALUES
(2,2,'paid',54,1,'2024-03-02 11:15:00',NULL,'Gift wrap 🎁',NULL);
INSERT INTO orders (id, customer_id, status, total, items, ordered_at, shipped_at, note, receipt) VALUES
(3,1,'cancelled',12.5,1,'2024-03-03 09:45:00',NULL,'Customer changed their mind',NULL);
INSERT INTO orders (id, customer_id, status, total, items, ordered_at, shipped_at, note, receipt) VALUES
(4,4,'shipped',980,12,'2024-03-05 02:10:00','2024-03-07 08:00:00','请小心轻放',X'25504446');
INSERT INTO orders (id, customer_id, status, total, items, ordered_at, shipped_at, note, receipt) VALUES
(5,5,'pending',45.75,2,'2024-03-08 17:20:00',NULL,'Leave at the door;
ring twice',NULL);
INSERT INTO orders (id, customer_id, status, total, items, ordered_at, shipped_at, note, receipt) VALUES
(6,6,'shipped',310.4,5,'2024-03-10 13:00:00','2024-03-11 09:00:00','Fragile: "glass"',NULL);
INSERT INTO orders (id, customer_id, status, total, items, ordered_at, shipped_at, note, receipt) VALUES
(7,8,'paid',76.2,2,'2024-03-11 18:45:00',NULL,NULL,NULL);
INSERT INTO orders (id, customer_id, status, total, items, ordered_at, shipped_at, note, receipt) VALUES
(8,2,'paid',19.99,1,'2024-03-12 08:00:00',NULL,'Paid at the counter',NULL);
INSERT INTO orders (id, customer_id, status, total, items, ordered_at, shipped_at, note, receipt) VALUES
(9,3,'shipped',64,2,'2024-03-14 15:30:00',NULL,'Shipping date never recorded',NULL);
INSERT INTO orders (id, customer_id, status, total, items, ordered_at, shipped_at, note, receipt) VALUES
(10,7,'paid',1499,1,'2024-03-15 21:05:00',NULL,'C:\Users\ravi\invoice.pdf',NULL);
-- Indexes, triggers and counters, after the rows so each index builds once.
CREATE UNIQUE INDEX customers_email ON customers (email);
CREATE INDEX orders_idx_orders_customer ON orders (customer_id);
CREATE INDEX orders_idx_orders_status_date ON orders (status, ordered_at);
UPDATE sqlite_sequence SET seq = max(seq, 8) WHERE name = 'customers';
INSERT INTO sqlite_sequence (name, seq) SELECT 'customers', 8 WHERE NOT EXISTS (SELECT 1 FROM sqlite_sequence WHERE name = 'customers');
UPDATE sqlite_sequence SET seq = max(seq, 10) WHERE name = 'orders';
INSERT INTO sqlite_sequence (name, seq) SELECT 'orders', 10 WHERE NOT EXISTS (SELECT 1 FROM sqlite_sequence WHERE name = 'orders');
COMMIT;
-- Rows whose foreign key finds no parent, if any: the load doesn't stop for them.
PRAGMA foreign_key_check;
Исправления
Исправлять ничего не пришлось.
Требует проверки
- Не конвертированы представления, триггеры, процедуры и события (2 объекта); отчет перечисляет каждый. Создайте их заново вручную в SQLite.
Файл конвертируется на этом компьютере и никуда не загружается.
Другие примеры:
Что меняется между файлом и скриптом
Каждая строка - это правило, которое применяет конвертер, и строка отчета, которую он пишет, когда правило что-то меняет в ваших данных.
declared types (any text: VARCHAR(255), DATETIME, BOOLEAN, JSON or none)
тип, в который помещается каждое значение столбца
Те же объявленные типы, поэтому значения загружаются так, как были сохранены.
BOOLEAN, BOOL
INTEGER 0 или 1 с CHECK
Если каждое значение равно 0 или 1; столбец, где есть и другие значения, сохраняет их как числа или текст.
TEXT, VARCHAR(n), CHAR(n), CLOB
объявленный тип, как есть
SQLite никогда не ограничивает длину; объявленная длина сохраняется, только если в нее помещается каждое значение.
DECIMAL(p,s), NUMERIC
точный тип, если в него помещается каждое значение, иначе double
SQLite хранит их как целые числа или double; объявленная точность сохраняется, только если значения в нее помещаются.
BLOB, and columns holding bytes
BLOB
Байты остаются байтами; текст и числа в том же столбце сохраняются как их байты.
DATE, DATETIME, TIMESTAMP holding ISO 8601 text
DATE, DATETIME как текст ISO 8601
Если каждое значение - дата или дата со временем; числа epoch и другой текст сохраняют свои значения как есть.
JSON holding JSON text
TEXT
Если каждое значение - объект или массив JSON.
Infinity in REAL columns
9e999, собственная бесконечность SQLite
SQLite записывает бесконечность как переполняющий литерал, который при загрузке снова становится бесконечностью.
INTEGER PRIMARY KEY, AUTOINCREMENT
INTEGER PRIMARY KEY, AUTOINCREMENT сохраняется
Только столбец, объявленный ровно как INTEGER PRIMARY KEY, является rowid; каждая строка сохраняет свой id, а счетчик начинается после наибольшего когда-либо выданного id.
COLLATE NOCASE
COLLATE NOCASE
То же сопоставление.
generated columns
генерируемые столбцы, STORED или VIRTUAL, как в источнике
SQLite вычисляет их так же.
generated columns with functions IntoSQL doesn't write, and the || operator
обычный столбец
Формула, которую нельзя записать, оставляет обычный столбец и строку в отчете; в дампе нет значений для генерируемых столбцов.
Строка отчета: generated_not_translated
defaults with functions IntoSQL doesn't write (strftime, randomblob)
без значения по умолчанию
Значение по умолчанию, которое нельзя записать, опускается и попадает в отчет; CURRENT_TIMESTAMP и datetime('now') записываются.
Строка отчета: default_not_translated
CHECK constraints
переводится
Те же проверки, применяемые при загрузке каждой строки.
CHECK constraints with functions IntoSQL doesn't write
не создается
Проверка, которую нельзя записать, опускается и попадает в отчет.
Строка отчета: check_skipped
partial and expression indexes
не создается
IntoSQL создает индексы по целым столбцам; остальные создайте заново после загрузки.
Строка отчета: index_skipped
foreign keys (unenforced unless PRAGMA foreign_keys=ON)
те же внешние ключи, список через PRAGMA foreign_key_check
SQLite проверяет внешние ключи, только если это включено, поэтому строки без родителя встречаются часто: они загружаются, а ключ остается непроверенным с предупреждением, вместо того чтобы остановить загрузку.
foreign keys to tables the dump doesn't create
не создается
Ключ не может ссылаться на таблицу, которой нет.
Строка отчета: foreign_key_skipped
primary keys holding NULL, and NOT NULL columns with values that become NULL
NOT NULL снимается
SQLite разрешает первичному ключу, кроме rowid, содержать NULL; в целевой базе столбец не может быть NOT NULL, иначе загрузка остановится.
Строка отчета: not_null_relaxed
views, triggers and virtual tables (FTS, R*Tree)
перечисляются в отчете
Их код написан на собственном языке SQLite, а виртуальным таблицам нужны модули SQLite; они перечислены, чтобы вы могли создать их заново. Их внутренние таблицы не копируются.
Строка отчета: not_converted_objects
dumps without CREATE TABLE (--data-only)
типы определяются по значениям
Дамп только с данными содержит лишь строки, поэтому типы берутся из значений, а столбцы нумеруются.
Строка отчета: no_schema
expressions in INSERT values other than the text functions dumps write
NULL
unistr(), replace(), char() и || вычисляются в том виде, в каком их пишет оболочка; другие выражения нельзя вычислить без базы данных.
Строка отчета: expression_value
NUL characters in text
сохраняется
Оболочка sqlite3 и Python обрезают текст на символе NUL при создании дампа, поэтому в дампе есть только то, что стоит перед ним.
text that isn't valid UTF-8
неверные байты заменяются символом замены
Дампы записывают такой текст как сырые байты; скрипт в UTF-8.
Строка отчета: invalid_utf8_replaced
text decoded twice (ñ)
копируется как есть
Дамп содержит именно эти символы, поэтому они копируются; отчет на них указывает.
Строка отчета: mojibake_suspected
| В файле | В скрипте | Строка отчета |
|---|---|---|
| declared types (any text: VARCHAR(255), DATETIME, BOOLEAN, JSON or none) | тип, в который помещается каждое значение столбцаТе же объявленные типы, поэтому значения загружаются так, как были сохранены. | |
| BOOLEAN, BOOL | INTEGER 0 или 1 с CHECKЕсли каждое значение равно 0 или 1; столбец, где есть и другие значения, сохраняет их как числа или текст. | |
| TEXT, VARCHAR(n), CHAR(n), CLOB | объявленный тип, как естьSQLite никогда не ограничивает длину; объявленная длина сохраняется, только если в нее помещается каждое значение. | |
| DECIMAL(p,s), NUMERIC | точный тип, если в него помещается каждое значение, иначе doubleSQLite хранит их как целые числа или double; объявленная точность сохраняется, только если значения в нее помещаются. | |
| BLOB, and columns holding bytes | BLOBБайты остаются байтами; текст и числа в том же столбце сохраняются как их байты. | |
| DATE, DATETIME, TIMESTAMP holding ISO 8601 text | DATE, DATETIME как текст ISO 8601Если каждое значение - дата или дата со временем; числа epoch и другой текст сохраняют свои значения как есть. | |
| JSON holding JSON text | TEXTЕсли каждое значение - объект или массив JSON. | |
| Infinity in REAL columns | 9e999, собственная бесконечность SQLiteSQLite записывает бесконечность как переполняющий литерал, который при загрузке снова становится бесконечностью. | |
| INTEGER PRIMARY KEY, AUTOINCREMENT | INTEGER PRIMARY KEY, AUTOINCREMENT сохраняетсяТолько столбец, объявленный ровно как INTEGER PRIMARY KEY, является rowid; каждая строка сохраняет свой id, а счетчик начинается после наибольшего когда-либо выданного id. | |
| COLLATE NOCASE | COLLATE NOCASEТо же сопоставление. | |
| generated columns | генерируемые столбцы, STORED или VIRTUAL, как в источникеSQLite вычисляет их так же. | |
| generated columns with functions IntoSQL doesn't write, and the || operator | обычный столбецФормула, которую нельзя записать, оставляет обычный столбец и строку в отчете; в дампе нет значений для генерируемых столбцов. | generated_not_translated |
| defaults with functions IntoSQL doesn't write (strftime, randomblob) | без значения по умолчаниюЗначение по умолчанию, которое нельзя записать, опускается и попадает в отчет; CURRENT_TIMESTAMP и datetime('now') записываются. | default_not_translated |
| CHECK constraints | переводитсяТе же проверки, применяемые при загрузке каждой строки. | |
| CHECK constraints with functions IntoSQL doesn't write | не создаетсяПроверка, которую нельзя записать, опускается и попадает в отчет. | check_skipped |
| partial and expression indexes | не создаетсяIntoSQL создает индексы по целым столбцам; остальные создайте заново после загрузки. | index_skipped |
| foreign keys (unenforced unless PRAGMA foreign_keys=ON) | те же внешние ключи, список через PRAGMA foreign_key_checkSQLite проверяет внешние ключи, только если это включено, поэтому строки без родителя встречаются часто: они загружаются, а ключ остается непроверенным с предупреждением, вместо того чтобы остановить загрузку. | |
| foreign keys to tables the dump doesn't create | не создаетсяКлюч не может ссылаться на таблицу, которой нет. | foreign_key_skipped |
| primary keys holding NULL, and NOT NULL columns with values that become NULL | NOT NULL снимаетсяSQLite разрешает первичному ключу, кроме rowid, содержать NULL; в целевой базе столбец не может быть NOT NULL, иначе загрузка остановится. | not_null_relaxed |
| views, triggers and virtual tables (FTS, R*Tree) | перечисляются в отчетеИх код написан на собственном языке SQLite, а виртуальным таблицам нужны модули SQLite; они перечислены, чтобы вы могли создать их заново. Их внутренние таблицы не копируются. | not_converted_objects |
| dumps without CREATE TABLE (--data-only) | типы определяются по значениямДамп только с данными содержит лишь строки, поэтому типы берутся из значений, а столбцы нумеруются. | no_schema |
| expressions in INSERT values other than the text functions dumps write | NULLunistr(), replace(), char() и || вычисляются в том виде, в каком их пишет оболочка; другие выражения нельзя вычислить без базы данных. | expression_value |
| NUL characters in text | сохраняетсяОболочка sqlite3 и Python обрезают текст на символе NUL при создании дампа, поэтому в дампе есть только то, что стоит перед ним. | |
| text that isn't valid UTF-8 | неверные байты заменяются символом заменыДампы записывают такой текст как сырые байты; скрипт в UTF-8. | invalid_utf8_replaced |
| text decoded twice (ñ) | копируется как естьДамп содержит именно эти символы, поэтому они копируются; отчет на них указывает. | mojibake_suspected |
Загрузите скрипт в SQLite
Скрипт создает таблицы, копирует строки, затем добавляет ключи, индексы и внешние ключи, поэтому загрузка идет быстро и останавливается на первой ошибке.
sqlite3 -bail mydb.sqlite < sqlite.sqlite.sqlВнешние ключи объявляются в каждой таблице, а строки загружаются с отключенной проверкой внешних ключей. Затем скрипт перечисляет все строки, которые ссылаются на несуществующие строки, а не прерывается на полпути.
Большой дамп загружайте в новый файл на локальном диске. Скрипт загружает все в одной транзакции с отключенной синхронизацией, поэтому работает со скоростью диска, а прерванная загрузка не оставляет неполных таблиц.
Командная строка загружает файл прямо в базу SQLite, без написания скрипта. Это бесплатно.
Как создать дамп SQLite для лучшего результата
Конвертер читает то, что есть в дампе. Эти параметры сохраняют в нем больше ваших данных:
- Сам файл базы данных конвертируется как есть и читается в браузере страница за страницей. Сначала закройте приложение, которое в него пишет, чтобы ни одно изменение не осталось в его файле -wal.
- sqlite3 app.db .dump > app.sql записывает ту же базу данных в SQL, который тоже конвертируется, в формате .sql или .sql.gz.
- DB Browser for SQLite пишет этот SQL через File, Export, Database to SQL file, как и iterdump() в Python.
Что не конвертируется
Представления, триггеры, процедуры, функции и другие объекты, написанные на собственном языке SQLite, перечислены в отчете по имени и никогда не удаляются молча, чтобы вы могли проверить каждый на той версии SQLite, в которую загружаете, прежде чем создать его заново.
Вопросы о переносе SQLite между версиями
Нет ответа на ваш вопрос? Напишите нам через страницу контактов, и вам ответит человек. Страница контактов
Мой дамп загружается на сервер?
Нет. Конвертер работает в вашем браузере и читает дамп с диска по частям, поэтому он никогда не покидает ваш компьютер. Приложение для компьютера и командная строка тоже конвертируют на вашем компьютере.
Насколько большим может быть дамп?
Конвертер никогда не держит весь дамп в памяти: он читает файл дважды, по диапазонам, и пишет скрипт по ходу чтения. Дампы в несколько гигабайт конвертируются в браузере, в приложении для компьютера и в командной строке.
Можно ли конвертировать сам файл .db?
Да. Перетащите файл .db, .sqlite или .sqlite3: он читается в браузере и никуда не загружается. Текст с символами NUL и все цифры значения double приходят такими, как хранятся, а .dump может их обрезать.
Из каких версий SQLite может быть дамп?
Файлы баз данных SQLite начиная с 3.0, в UTF-8 или UTF-16, и дампы из .dump оболочки sqlite3 или из iterdump() в Python. Каждый тестовый файл и дамп создан в sqlite3 с 3.31 по 3.54, включая таблицы STRICT и WITHOUT ROWID, и сверен с источником ячейка за ячейкой.
Как определяются типы столбцов, если SQLite их не соблюдает?
Каждый столбец сохраняет объявленный тип, как и COLLATE NOCASE и RTRIM. STRICT опускается, поэтому скрипт загружается на любой версии начиная с 3.31.
Сохраняются ли INTEGER PRIMARY KEY и AUTOINCREMENT?
Да. INTEGER PRIMARY KEY и AUTOINCREMENT остаются как есть, а sqlite_sequence продолжается с того места, где его оставил дамп.
А представления и триггеры?
Они перечислены в отчете по имени и не конвертируются, чтобы вы могли создать их заново, когда таблицы будут загружены.
На каких версиях SQLite загружается скрипт?
SQLite 3.31 и новее. Каждый тестовый файл и дамп загружается на 3.31 и 3.54 и останавливается на первой ошибке, если что-то пойдет не так.