Aller au contenu
Accueil IntoSQL

Passer une base SQLite vers un SQLite plus ancien ou plus récent

Déposez un fichier de base SQLite (.db, .sqlite, .sqlite3) ou le SQL qu'écrit .dump de sqlite3, et téléchargez un script qui se charge sur SQLite 3.31 et suivants. Chaque colonne garde son type déclaré et sa collation, STRICT est retiré pour que les versions plus anciennes acceptent les tables, et chaque changement figure dans le rapport.

Votre fichier
sqlshop_2024_sqlite.sqlFichier d'exemple, 3,4 ko
Votre base de données

18 lignes converties, aucune correction, aucune rejetée

Afficher

Tables de shop_2024_sqlite.sqlDump SQLite · écrit par sqlite3 · utf-8

  • customers8 lignes
    7 colonnes
    idINTEGER not null
    nameTEXT not null
    emailTEXT not null
    countryTEXT not null
    is_activeINTEGER not null
    signed_upDATE
    created_atDATETIME not null
  • orders10 lignes
    9 colonnes
    idINTEGER not null
    customer_idINTEGER not null
    statusTEXT not null
    totalDECIMAL(10,2) not null
    itemsINTEGER not null
    ordered_atDATETIME not null
    shipped_atDATETIME
    noteTEXT
    receiptBLOB

Non converti

  • Vue order_totals
  • Déclencheur orders_shipped

Chaque base de données les écrit dans son propre langage. Réécrivez-les pour 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;

Corrections

Rien n'avait besoin d'être corrigé.

À vérifier

  • 2 objets non convertis (vues, déclencheurs, routines ou événements) ; le rapport les liste un par un. Recréez-les à la main dans SQLite.

Votre fichier est converti sur cet ordinateur et n'est jamais envoyé.

Autres exemples :

Ce qui change entre le fichier et le script

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

    Les mêmes types déclarés, donc les valeurs se chargent telles qu'elles étaient stockées.

  • BOOLEAN, BOOL

    INTEGER 0 ou 1 avec un CHECK

    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

    le type déclaré, gardé tel quel

    SQLite n'impose jamais de longueur ; une longueur déclarée n'est gardée que si chaque valeur y tient.

  • 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

    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 en texte ISO 8601

    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

    TEXT

    Quand chaque valeur est un objet ou un tableau JSON.

  • Infinity in REAL columns

    9e999, l'infini propre à SQLite

    SQLite écrit l'infini sous forme de littéral qui déborde, qui se recharge comme l'infini.

  • INTEGER PRIMARY KEY, AUTOINCREMENT

    INTEGER PRIMARY KEY, AUTOINCREMENT conservé

    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

    COLLATE NOCASE

    La même collation.

  • generated columns

    colonnes générées, STORED ou VIRTUAL comme dans la source

    SQLite 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

    Les mêmes contraintes CHECK, vérifiées 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)

    les mêmes clés étrangères, listées par PRAGMA foreign_key_check

    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 le fichierDans le scriptLigne du rapport
declared types (any text: VARCHAR(255), DATETIME, BOOLEAN, JSON or none)le type auquel chaque valeur de la colonne correspondLes mêmes types déclarés, donc les valeurs se chargent telles qu'elles étaient stockées.
BOOLEAN, BOOLINTEGER 0 ou 1 avec un CHECKQuand 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), CLOBle type déclaré, gardé tel quelSQLite n'impose jamais de longueur ; une longueur déclarée n'est gardée que si chaque valeur y tient.
DECIMAL(p,s), NUMERICle 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 bytesBLOBLes 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 textDATE, DATETIME en texte ISO 8601Quand 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 textTEXTQuand chaque valeur est un objet ou un tableau JSON.
Infinity in REAL columns9e999, l'infini propre à SQLiteSQLite écrit l'infini sous forme de littéral qui déborde, qui se recharge comme l'infini.
INTEGER PRIMARY KEY, AUTOINCREMENTINTEGER PRIMARY KEY, AUTOINCREMENT conservé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 NOCASECOLLATE NOCASELa même collation.
generated columnscolonnes générées, STORED ou VIRTUAL comme dans la sourceSQLite les calcule de la même façon.
generated columns with functions IntoSQL doesn't write, and the || operatorune 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 constraintstraduitesLes mêmes contraintes CHECK, vérifiées au chargement de chaque ligne.
CHECK constraints with functions IntoSQL doesn't writenon crééeUne contrainte CHECK qui ne peut pas être écrite est omise et signalée.check_skipped
partial and expression indexesnon 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)les mêmes clés étrangères, listées par PRAGMA foreign_key_checkSQLite 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 createnon 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 NULLNOT 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 writeNULLunistr(), 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 textconservé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-8les 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 SQLite

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.

sqlite3 -bail mydb.sqlite < sqlite.sqlite.sql

Les clés étrangères sont déclarées dans chaque table et les lignes se chargent sans vérification des clés étrangères. Le script liste ensuite toute ligne qui pointe vers une ligne qui n'existe pas, au lieu d'échouer à mi-chemin.

Pour un gros dump, chargez-le dans un nouveau fichier sur un disque local. Le script charge tout dans une seule transaction sans synchronisation, il va donc à la vitesse du disque, et un chargement interrompu ne laisse aucune table partielle.

La ligne de commande charge le fichier directement dans une base SQLite, sans écrire de script. C'est gratuit.

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, triggers, procédures, fonctions et autres objets écrits dans le propre langage de SQLite sont listés par nom dans le rapport, jamais supprimés en silence, pour que vous vérifiiez chacun face à la version de SQLite cible avant de le recréer.

Questions sur le passage de SQLite d'une version à l'autre

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 ?

Chaque colonne garde son type déclaré, tout comme COLLATE NOCASE et RTRIM. STRICT est omis, donc le script se charge sur toutes les versions depuis 3.31.

INTEGER PRIMARY KEY et AUTOINCREMENT sont-ils conservés ?

Oui. INTEGER PRIMARY KEY et AUTOINCREMENT restent tels quels, et sqlite_sequence reprend là où le dump l'a laissé.

Et les vues et les déclencheurs ?

Ils sont listés par nom dans le rapport et ne sont pas convertis, pour que vous puissiez les recréer une fois les tables en place.

Sur quelles versions de SQLite le script se charge-t-il ?

SQLite 3.31 et versions ultérieures. Chaque fichier et dump de test se charge sur 3.31 et 3.54, et s'arrête à la première erreur en cas de problème.