Convertir SQLite en MySQL
Déposez un fichier de base de données SQLite (.db, .sqlite, .sqlite3) ou le SQL qu'écrit le .dump de sqlite3, et téléchargez un script MySQL avec les mêmes tables, clés, index et données. Chaque colonne reçoit le type auquel ses valeurs correspondent, et chaque valeur que MySQL ne peut pas contenir telle quelle est listée dans le rapport.
18 lignes converties, aucune correction, aucune rejetée
Tables de shop_2024_sqlite.sqlDump SQLite · écrit par sqlite3 · utf-8
customers8 lignes
7 colonnes id bigint not null name text not null email varchar(768) not null country varchar(768) not null is_active tinyint(1) not null signed_up date created_at datetime not null orders10 lignes
9 colonnes id bigint not null customer_id bigint not null status varchar(768) not null total decimal(10,2) not null items int not null ordered_at datetime not null shipped_at datetime note text receipt blob
Non converti
- Vue order_totals
- Déclencheur orders_shipped
Chaque base de données les écrit dans son propre langage. Réécrivez-les pour MySQL.
-- Written by IntoSQL from a SQLite dump. Load it with: mysql --default-character-set=utf8mb4 <database> < <file>
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
SET UNIQUE_CHECKS = 0;
SET SQL_MODE = 'NO_AUTO_VALUE_ON_ZERO,ALLOW_INVALID_DATES';
CREATE TABLE `customers` (
`id` bigint NOT NULL AUTO_INCREMENT,
`name` text NOT NULL,
`email` varchar(768) NOT NULL,
`country` varchar(768) NOT NULL DEFAULT 'US',
`is_active` tinyint(1) NOT NULL DEFAULT 1,
`signed_up` date,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`),
CONSTRAINT `check1` CHECK (char_length(`country`) = 2)
) AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
CREATE TABLE `orders` (
`id` bigint NOT NULL AUTO_INCREMENT,
`customer_id` bigint NOT NULL,
`status` varchar(768) NOT NULL DEFAULT 'pending',
`total` decimal(10,2) NOT NULL,
`items` int NOT NULL DEFAULT 1,
`ordered_at` datetime NOT NULL,
`shipped_at` datetime,
`note` text,
`receipt` blob,
PRIMARY KEY (`id`),
KEY `idx_orders_customer` (`customer_id`),
KEY `idx_orders_status_date` (`status`,`ordered_at`),
CONSTRAINT `check1` CHECK (`status` IN ('pending', 'paid', 'shipped', 'cancelled')),
FOREIGN KEY (`customer_id`) REFERENCES `customers` (`id`) ON DELETE CASCADE
) AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
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;\nring 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);
SET UNIQUE_CHECKS = 1;
SET FOREIGN_KEY_CHECKS = 1;
Corrections
Rien n'avait besoin d'être corrigé.
À vérifier
- 1 colonne de texte compare sans tenir compte de la casse dans la source ; MySQL compare exactement, donc les clés uniques et les recherches peuvent se comporter autrement. Utilisez une collation ou un type de colonne insensible à la casse sur les colonnes qui en ont besoin.
- 2 objets non convertis (vues, déclencheurs, routines ou événements) ; le rapport les liste un par un. Recréez-les à la main dans MySQL.
Votre fichier est converti sur cet ordinateur et n'est jamais envoyé.
Autres exemples :
Ce qui change de SQLite à MySQL
Chaque ligne est une règle appliquée par le convertisseur, avec la ligne de rapport qu'il écrit quand la règle change quelque chose dans vos données.
declared types (any text: VARCHAR(255), DATETIME, BOOLEAN, JSON or none)
le type auquel chaque valeur de la colonne correspond
SQLite accepte n'importe quelle valeur dans n'importe quelle colonne, donc le type déclaré est une indication : chaque colonne reçoit le type auquel toutes ses valeurs correspondent, et une colonne aux valeurs mélangées garde leur texte.
BOOLEAN, BOOL
tinyint(1)
Quand chaque valeur vaut 0 ou 1 ; une colonne qui contient aussi d'autres valeurs les garde en nombres ou en texte.
TEXT, VARCHAR(n), CHAR(n), CLOB
varchar(n) jusqu'à 1024 caractères, types text au-delà
SQLite n'impose jamais de longueur ; une longueur déclarée n'est gardée que si chaque valeur y tient. Le texte dans une clé, ou avec une valeur par défaut, est varchar(768) si ses valeurs y tiennent, ce que MySQL 5.7 peut indexer et doter d'une valeur par défaut.
DECIMAL(p,s), NUMERIC
le type exact si chaque valeur y tient, sinon un double
SQLite les stocke en entiers ou en doubles ; une précision déclarée n'est gardée que si les valeurs y tiennent.
BLOB, and columns holding bytes
types blob
Les octets restent des octets ; le texte et les nombres de la même colonne sont gardés sous forme d'octets.
DATE, DATETIME, TIMESTAMP holding ISO 8601 text
date, datetime(p)
Quand chaque valeur est une date ou une date et une heure ; les nombres epoch et les autres textes gardent leurs valeurs telles quelles.
JSON holding JSON text
json
Quand chaque valeur est un objet ou un tableau JSON.
Infinity in REAL columns
NULL
Les doubles de MySQL n'ont pas d'infini ; ces valeurs deviennent donc NULL et le rapport les compte.
Ligne du rapport: invalid_value_null
INTEGER PRIMARY KEY, AUTOINCREMENT
AUTO_INCREMENT, qui reprend après l'identifiant le plus élevé ou celui de sqlite_sequence
Seule une colonne déclarée exactement INTEGER PRIMARY KEY est le rowid ; chaque ligne garde son identifiant, et le compteur reprend après le plus grand identifiant jamais attribué.
COLLATE NOCASE
comparaison exacte (utf8mb4_bin)
Les tables utilisent utf8mb4_bin pour que le texte se compare exactement, comme par défaut dans SQLite ; les colonnes NOCASE ne sont plus insensibles à la casse.
Ligne du rapport: case_insensitive_collation
generated columns
colonnes générées, STORED ou VIRTUAL comme dans la source
MySQL les calcule de la même façon.
generated columns with functions IntoSQL doesn't write, and the || operator
une colonne simple
Une formule qui ne peut pas être écrite laisse une colonne simple et une ligne dans le rapport ; le dump ne contient aucune valeur pour les colonnes générées.
Ligne du rapport: generated_not_translated
defaults with functions IntoSQL doesn't write (strftime, randomblob)
aucune valeur par défaut
Une valeur par défaut qui ne peut pas être écrite est omise et signalée ; CURRENT_TIMESTAMP et datetime('now') sont écrits.
Ligne du rapport: default_not_translated
CHECK constraints
traduites
MySQL 5.7 les garde sans les vérifier ; les autres versions les vérifient au chargement de chaque ligne.
CHECK constraints with functions IntoSQL doesn't write
non créée
Une contrainte CHECK qui ne peut pas être écrite est omise et signalée.
Ligne du rapport: check_skipped
partial and expression indexes
non créée
IntoSQL écrit des index sur des colonnes entières ; recréez les autres après le chargement.
Ligne du rapport: index_skipped
foreign keys (unenforced unless PRAGMA foreign_keys=ON)
clés étrangères, chargées avec FOREIGN_KEY_CHECKS=0
SQLite ne vérifie les clés étrangères que si on le lui demande, donc les lignes sans parent sont courantes : elles se chargent, et la clé reste non vérifiée avec un avertissement au lieu d'arrêter le chargement.
foreign keys to tables the dump doesn't create
non créée
Une clé ne peut pas désigner une table absente.
Ligne du rapport: foreign_key_skipped
primary keys holding NULL, and NOT NULL columns with values that become NULL
NOT NULL retiré
SQLite permet à une clé primaire autre que le rowid de contenir NULL ; la colonne ne peut pas être NOT NULL dans la cible, sinon le chargement s'arrêterait.
Ligne du rapport: not_null_relaxed
views, triggers and virtual tables (FTS, R*Tree)
listés dans le rapport
Leur code est écrit dans le langage propre à SQLite, et les tables virtuelles ont besoin des modules de SQLite ; ils sont listés pour que vous les recréiez. Leurs tables internes ne sont pas copiées.
Ligne du rapport: not_converted_objects
dumps without CREATE TABLE (--data-only)
types déduits des valeurs
Un dump de données seules ne contient que des lignes, donc les types viennent des valeurs et les colonnes sont numérotées.
Ligne du rapport: no_schema
expressions in INSERT values other than the text functions dumps write
NULL
unistr(), replace(), char() et || sont évalués tels que le shell les écrit ; les autres expressions ne peuvent pas l'être sans base de données.
Ligne du rapport: expression_value
NUL characters in text
conservé
Le shell sqlite3 et Python coupent le texte à un caractère NUL quand ils le dumpent ; seul ce qui le précède est donc dans le dump.
text that isn't valid UTF-8
les octets invalides deviennent le caractère de remplacement
Les dumps écrivent ce texte en octets bruts ; le script est en UTF-8.
Ligne du rapport: invalid_utf8_replaced
text decoded twice (ñ)
copié tel quel
Le dump contient exactement ces caractères, ils sont donc copiés ; le rapport les signale.
Ligne du rapport: mojibake_suspected
| Dans SQLite | Dans MySQL | Ligne du rapport |
|---|---|---|
| declared types (any text: VARCHAR(255), DATETIME, BOOLEAN, JSON or none) | le type auquel chaque valeur de la colonne correspondSQLite accepte n'importe quelle valeur dans n'importe quelle colonne, donc le type déclaré est une indication : chaque colonne reçoit le type auquel toutes ses valeurs correspondent, et une colonne aux valeurs mélangées garde leur texte. | |
| BOOLEAN, BOOL | tinyint(1)Quand chaque valeur vaut 0 ou 1 ; une colonne qui contient aussi d'autres valeurs les garde en nombres ou en texte. | |
| TEXT, VARCHAR(n), CHAR(n), CLOB | varchar(n) jusqu'à 1024 caractères, types text au-delàSQLite n'impose jamais de longueur ; une longueur déclarée n'est gardée que si chaque valeur y tient. Le texte dans une clé, ou avec une valeur par défaut, est varchar(768) si ses valeurs y tiennent, ce que MySQL 5.7 peut indexer et doter d'une valeur par défaut. | |
| DECIMAL(p,s), NUMERIC | le type exact si chaque valeur y tient, sinon un doubleSQLite les stocke en entiers ou en doubles ; une précision déclarée n'est gardée que si les valeurs y tiennent. | |
| BLOB, and columns holding bytes | types blobLes octets restent des octets ; le texte et les nombres de la même colonne sont gardés sous forme d'octets. | |
| DATE, DATETIME, TIMESTAMP holding ISO 8601 text | date, datetime(p)Quand chaque valeur est une date ou une date et une heure ; les nombres epoch et les autres textes gardent leurs valeurs telles quelles. | |
| JSON holding JSON text | jsonQuand chaque valeur est un objet ou un tableau JSON. | |
| Infinity in REAL columns | NULLLes doubles de MySQL n'ont pas d'infini ; ces valeurs deviennent donc NULL et le rapport les compte. | invalid_value_null |
| INTEGER PRIMARY KEY, AUTOINCREMENT | AUTO_INCREMENT, qui reprend après l'identifiant le plus élevé ou celui de sqlite_sequenceSeule une colonne déclarée exactement INTEGER PRIMARY KEY est le rowid ; chaque ligne garde son identifiant, et le compteur reprend après le plus grand identifiant jamais attribué. | |
| COLLATE NOCASE | comparaison exacte (utf8mb4_bin)Les tables utilisent utf8mb4_bin pour que le texte se compare exactement, comme par défaut dans SQLite ; les colonnes NOCASE ne sont plus insensibles à la casse. | case_insensitive_collation |
| generated columns | colonnes générées, STORED ou VIRTUAL comme dans la sourceMySQL les calcule de la même façon. | |
| generated columns with functions IntoSQL doesn't write, and the || operator | une colonne simpleUne formule qui ne peut pas être écrite laisse une colonne simple et une ligne dans le rapport ; le dump ne contient aucune valeur pour les colonnes générées. | generated_not_translated |
| defaults with functions IntoSQL doesn't write (strftime, randomblob) | aucune valeur par défautUne valeur par défaut qui ne peut pas être écrite est omise et signalée ; CURRENT_TIMESTAMP et datetime('now') sont écrits. | default_not_translated |
| CHECK constraints | traduitesMySQL 5.7 les garde sans les vérifier ; les autres versions les vérifient au chargement de chaque ligne. | |
| CHECK constraints with functions IntoSQL doesn't write | non crééeUne contrainte CHECK qui ne peut pas être écrite est omise et signalée. | check_skipped |
| partial and expression indexes | non crééeIntoSQL écrit des index sur des colonnes entières ; recréez les autres après le chargement. | index_skipped |
| foreign keys (unenforced unless PRAGMA foreign_keys=ON) | clés étrangères, chargées avec FOREIGN_KEY_CHECKS=0SQLite ne vérifie les clés étrangères que si on le lui demande, donc les lignes sans parent sont courantes : elles se chargent, et la clé reste non vérifiée avec un avertissement au lieu d'arrêter le chargement. | |
| foreign keys to tables the dump doesn't create | non crééeUne clé ne peut pas désigner une table absente. | foreign_key_skipped |
| primary keys holding NULL, and NOT NULL columns with values that become NULL | NOT NULL retiréSQLite permet à une clé primaire autre que le rowid de contenir NULL ; la colonne ne peut pas être NOT NULL dans la cible, sinon le chargement s'arrêterait. | not_null_relaxed |
| views, triggers and virtual tables (FTS, R*Tree) | listés dans le rapportLeur code est écrit dans le langage propre à SQLite, et les tables virtuelles ont besoin des modules de SQLite ; ils sont listés pour que vous les recréiez. Leurs tables internes ne sont pas copiées. | not_converted_objects |
| dumps without CREATE TABLE (--data-only) | types déduits des valeursUn dump de données seules ne contient que des lignes, donc les types viennent des valeurs et les colonnes sont numérotées. | no_schema |
| expressions in INSERT values other than the text functions dumps write | NULLunistr(), replace(), char() et || sont évalués tels que le shell les écrit ; les autres expressions ne peuvent pas l'être sans base de données. | expression_value |
| NUL characters in text | conservéLe shell sqlite3 et Python coupent le texte à un caractère NUL quand ils le dumpent ; seul ce qui le précède est donc dans le dump. | |
| text that isn't valid UTF-8 | les octets invalides deviennent le caractère de remplacementLes dumps écrivent ce texte en octets bruts ; le script est en UTF-8. | invalid_utf8_replaced |
| text decoded twice (ñ) | copié tel quelLe dump contient exactement ces caractères, ils sont donc copiés ; le rapport les signale. | mojibake_suspected |
Charger le script dans MySQL
Le script crée les tables, copie les lignes, puis ajoute les clés, les index et les clés étrangères ; il se charge donc vite et s'arrête à la première erreur.
mysql --default-character-set=utf8mb4 mydb < sqlite.mysql.sqlLes clés étrangères sont créées comme le dump les déclare, avec FOREIGN_KEY_CHECKS=0 pendant le chargement des lignes ; une ligne qui pointe vers une ligne absente n'arrête donc pas le chargement.
Pour un gros dump, exécutez le client sur la machine du serveur, et augmentez max_allowed_packet si une seule ligne est très grande.
IntoSQL Pro charge le fichier directement dans MySQL depuis l'application de bureau ou la ligne de commande, sans écrire de script.
Faire le dump SQLite pour un meilleur résultat
Le convertisseur lit ce que contient le dump. Ces options y gardent davantage de vos données :
- Le fichier de base de données lui-même se convertit tel quel, lu page par page dans votre navigateur. Fermez d'abord l'application qui y écrit, pour qu'aucun changement ne reste dans son fichier -wal.
- sqlite3 app.db .dump > app.sql écrit la même base de données en SQL, qui se convertit aussi, en .sql ou .sql.gz.
- DB Browser for SQLite écrit ce SQL avec File, Export, Database to SQL file, tout comme iterdump() de Python.
Ce qui n'est pas converti
Les vues et les déclencheurs sont écrits dans le langage propre à SQLite. Ils sont listés par nom dans le rapport, jamais supprimés en silence, pour que vous puissiez les réécrire pour MySQL. Les tables virtuelles, comme FTS5 et R*Tree, sont listées aussi, et leurs tables internes sont omises.
Questions sur SQLite vers MySQL
Pas de réponse ici ? Écrivez-nous depuis la page de contact, une personne vous répond. Page de contact
Mon dump est-il envoyé ?
Non. Le convertisseur s'exécute dans votre navigateur et lit le dump depuis votre disque par morceaux ; il ne quitte donc jamais votre ordinateur. L'application de bureau et la ligne de commande convertissent aussi sur votre ordinateur.
Quelle taille peut avoir le dump ?
Le convertisseur ne garde jamais tout le dump en mémoire : il lit le fichier deux fois, par plages, et écrit le script au fur et à mesure. Les dumps de plusieurs gigaoctets se convertissent dans le navigateur, dans l'application de bureau et avec la ligne de commande.
Puis-je convertir le fichier .db lui-même ?
Oui. Déposez le fichier .db, .sqlite ou .sqlite3 : il est lu dans votre navigateur et jamais envoyé. Le texte avec des caractères NUL et chaque chiffre d'un double arrivent tels qu'ils sont stockés, ce qu'un .dump peut tronquer.
De quelles versions de SQLite le dump peut-il venir ?
Les fichiers de base de données de SQLite 3.0 et après, en UTF-8 ou UTF-16, et les dumps du .dump du shell sqlite3 ou de iterdump() de Python. Chaque fichier et dump de test vient de sqlite3 3.31 à 3.54, tables STRICT et WITHOUT ROWID comprises, et est comparé à sa source cellule par cellule.
Comment les types de colonnes sont-ils décidés quand SQLite ne les impose pas ?
Le type déclaré est une indication et les valeurs décident : une colonne devient un type integer, decimal, double, date, datetime, tinyint(1), blob ou text quand chaque valeur y correspond. Le texte dans une clé ou avec une valeur par défaut est varchar(768), pour que MySQL 5.7 puisse l'indexer.
INTEGER PRIMARY KEY et AUTOINCREMENT sont-ils conservés ?
Oui. Un INTEGER PRIMARY KEY devient AUTO_INCREMENT, chaque ligne garde son identifiant, et le prochain identifiant reprend après le plus élevé, ou après la valeur de sqlite_sequence avec AUTOINCREMENT.
Et les vues et les déclencheurs ?
Ils sont listés par nom dans le rapport et ne sont pas convertis, car chaque base de données les écrit dans son propre langage.
Sur quelles versions de MySQL le script se charge-t-il ?
MySQL 5.7 et versions ultérieures. Chaque dump de test se charge sur 5.7 et 9, et s'arrête à la première erreur en cas de problème.