254 votes

Un moyen rapide et facile de migrer SQLite3 vers MySQL ?

Quelqu'un connaît-il un moyen simple et rapide de migrer une base de données SQLite3 vers MySQL ?

125voto

Shalmanese Points 2518

Tout le monde semble commencer avec quelques expressions greps et perl et vous obtenez en quelque sorte quelque chose qui fonctionne pour votre ensemble de données particulier mais vous n'avez aucune idée si cela a importé les données correctement ou non. Je suis sérieusement surpris que personne n'ait construit une bibliothèque solide qui puisse convertir entre les deux.

Voici une liste de TOUTES les différences de syntaxe SQL que je connais entre les deux formats de fichier : Les lignes commençant par :

  • COMMENCER LA TRANSACTION
  • COMMIT
  • sqlite_séquence
  • CRÉER UN INDEX UNIQUE

ne sont pas utilisés dans MySQL

  • SQLite utilise CREATE TABLE/INSERT INTO "table_name" et MySQL utilise CREATE TABLE/INSERT INTO table_name
  • MySQL n'utilise pas les guillemets dans la définition du schéma.
  • MySQL utilise des guillemets simples pour les chaînes de caractères à l'intérieur du champ INSERT INTO clauses
  • SQLite et MySQL ont des manières différentes d'échapper les chaînes de caractères à l'intérieur des fichiers INSERT INTO clauses
  • SQLite utilise 't' et 'f' pour les booléens, MySQL utilise 1 et 0 (une simple regex pour cela peut échouer lorsque vous avez une chaîne comme : 'Je le fais, tu ne le fais pas' à l'intérieur de votre INSERT INTO )
  • SQLLite utilise AUTOINCREMENT MySQL utilise AUTO_INCREMENT

Voici un script perl bidouillé très basique qui fonctionne pour mon et vérifie beaucoup plus de ces conditions que d'autres scripts perl que j'ai trouvé sur le web. Je ne garantis pas qu'il fonctionnera pour vos données mais n'hésitez pas à le modifier et à le poster ici.

#! /usr/bin/perl

while ($line = <>){
    if (($line !~  /BEGIN TRANSACTION/) && ($line !~ /COMMIT/) && ($line !~ /sqlite_sequence/) && ($line !~ /CREATE UNIQUE INDEX/)){

        if ($line =~ /CREATE TABLE \"([a-z_]*)\"(.*)/i){
            $name = $1;
            $sub = $2;
            $sub =~ s/\"//g;
            $line = "DROP TABLE IF EXISTS $name;\nCREATE TABLE IF NOT EXISTS $name$sub\n";
        }
        elsif ($line =~ /INSERT INTO \"([a-z_]*)\"(.*)/i){
            $line = "INSERT INTO $1$2\n";
            $line =~ s/\"/\\\"/g;
            $line =~ s/\"/\'/g;
        }else{
            $line =~ s/\'\'/\\\'/g;
        }
        $line =~ s/([^\\'])\'t\'(.)/$1THIS_IS_TRUE$2/g;
        $line =~ s/THIS_IS_TRUE/1/g;
        $line =~ s/([^\\'])\'f\'(.)/$1THIS_IS_FALSE$2/g;
        $line =~ s/THIS_IS_FALSE/0/g;
        $line =~ s/AUTOINCREMENT/AUTO_INCREMENT/g;
        print $line;
    }
}

11 votes

Alex Martelli a fait un excellent travail de réécriture en python à l'adresse suivante stackoverflow.com/questions/1067060/perl-to-python

0 votes

J'ai ajouté le script python complet (le script perl seul ne fonctionnait pas tout à fait pour moi... j'avais besoin d'un traitement supplémentaire pour gérer les clés étrangères et les index).

0 votes

J'ai réécrit cette réponse sur l'autre question stackoverflow.com/questions/1067060/_/1070463#1070463

68voto

David d C e Freitas Points 4136

Voici une liste de convertisseurs (non mise à jour depuis 2011) :


Une autre méthode qui fonctionnerait bien, mais qui est rarement mentionnée, consiste à utiliser une classe ORM qui fait abstraction des différences entre les bases de données. RedBean ), Python (la couche ORM de Django, Tempête , SqlAlchemy ), Ruby on Rails ( ActiveRecord ), Cacao ( Données de base )

c'est-à-dire que vous pourriez faire ça :

  1. Chargez les données de la base de données source en utilisant la classe ORM.
  2. Stocker les données en mémoire ou les sérialiser sur le disque.
  3. Stockez les données dans la base de données de destination en utilisant la classe ORM.

0 votes

Faut-il faire des modèles pour utiliser les ORM ?

56voto

Jiaaro Points 14379

Voici un python script, construit à partir de la réponse de Shalmanese et de l'aide d'Alex martelli à l'adresse suivante Traduire Perl en Python

J'en fais un wiki communautaire, alors n'hésitez pas à le modifier et à le remanier tant qu'il ne casse pas la fonctionnalité (heureusement, nous pouvons simplement revenir en arrière).

utiliser comme suit (en supposant que le script est appelé dump_for_mysql.py :

sqlite3 sample.db .dump | python dump_for_mysql.py > dump.sql

Que vous pouvez ensuite importer dans mysql

note - vous devez ajouter les contraintes de clé étrangère manuellement car sqlite ne les supporte pas vraiment.

voici le script :

#!/usr/bin/env python

import re
import fileinput

def this_line_is_useless(line):
    useless_es = [
        'BEGIN TRANSACTION',
        'COMMIT',
        'sqlite_sequence',
        'CREATE UNIQUE INDEX',
        'PRAGMA foreign_keys=OFF',
    ]
    for useless in useless_es:
        if re.search(useless, line):
            return True

def has_primary_key(line):
    return bool(re.search(r'PRIMARY KEY', line))

searching_for_end = False
for line in fileinput.input():
    if this_line_is_useless(line):
        continue

    # this line was necessary because '');
    # would be converted to \'); which isn't appropriate
    if re.match(r".*, ''\);", line):
        line = re.sub(r"''\);", r'``);', line)

    if re.match(r'^CREATE TABLE.*', line):
        searching_for_end = True

    m = re.search('CREATE TABLE "?(\w*)"?(.*)', line)
    if m:
        name, sub = m.groups()
        line = "DROP TABLE IF EXISTS %(name)s;\nCREATE TABLE IF NOT EXISTS `%(name)s`%(sub)s\n"
        line = line % dict(name=name, sub=sub)
    else:
        m = re.search('INSERT INTO "(\w*)"(.*)', line)
        if m:
            line = 'INSERT INTO %s%s\n' % m.groups()
            line = line.replace('"', r'\"')
            line = line.replace('"', "'")
    line = re.sub(r"([^'])'t'(.)", "\1THIS_IS_TRUE\2", line)
    line = line.replace('THIS_IS_TRUE', '1')
    line = re.sub(r"([^'])'f'(.)", "\1THIS_IS_FALSE\2", line)
    line = line.replace('THIS_IS_FALSE', '0')

    # Add auto_increment if it is not there since sqlite auto_increments ALL
    # primary keys
    if searching_for_end:
        if re.search(r"integer(?:\s+\w+)*\s*PRIMARY KEY(?:\s+\w+)*\s*,", line):
            line = line.replace("PRIMARY KEY", "PRIMARY KEY AUTO_INCREMENT")
        # replace " and ' with ` because mysql doesn't like quotes in CREATE commands 
        if line.find('DEFAULT') == -1:
            line = line.replace(r'"', r'`').replace(r"'", r'`')
        else:
            parts = line.split('DEFAULT')
            parts[0] = parts[0].replace(r'"', r'`').replace(r"'", r'`')
            line = 'DEFAULT'.join(parts)

    # And now we convert it back (see above)
    if re.match(r".*, ``\);", line):
        line = re.sub(r'``\);', r"'');", line)

    if searching_for_end and re.match(r'.*\);', line):
        searching_for_end = False

    if re.match(r"CREATE INDEX", line):
        line = re.sub('"', '`', line)

    if re.match(r"AUTOINCREMENT", line):
        line = re.sub("AUTOINCREMENT", "AUTO_INCREMENT", line)

    print line,

2 votes

Bonjour Jim, sur mon jeu de données, chaque première instruction INSERT est entourée d'une apostrophe au lieu d'une simple citation : __ DROP TABLE IF EXISTS schema_migrations ; CREATE TABLE IF NOT EXISTS schema_migrations ( version varchar(255) NOT NULL) ; INSERT INTO schema_migrations VALUES( 20100714032840 ) ; INSERT INTO schema_migrations VALUES('20100714033251') ; __.

0 votes

Eh bien... cela n'apparaît pas ci-dessus, mais les guillemets apparaissent à l'intérieur des VALUES ([HERE]20100714032840[/HERE])

1 votes

L'AUTOINCREMENT dans Mysql est AUTO_INCREMENT. Le script ne tient pas compte de cela.

22voto

ryw Points 2852

C'est compliqué car les fichiers de vidage sont spécifiques aux fournisseurs de bases de données.

Si vous utilisez Rails, il existe un excellent plugin pour cela. Lire : http://blog.heroku.com/archives/2007/11/23/yamldb_for_databaseindependent_data_dumps/

Mise à jour

Fourchette actuellement entretenue : https://github.com/ludicast/yaml_db

8voto

pdxleif Points 361

Je suis surpris que personne ne l'ait encore mentionné, mais il existe un outil spécialement conçu pour cela. Il est en perl, SQL:Translator : http://sqlfairy.sourceforge.net/

Convertit entre la plupart des formes de données tabulaires (différents formats SQL, feuille de calcul Excel), et réalise même des diagrammes de votre schéma SQL.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X