Question

Quelqu'un connait un moyen rapide et facile pour migrer une base de données SQLite3 pour MySQL?

Était-ce utile?

La solution

Voici une liste des convertisseurs (pas mis à jour depuis 2011):


Une autre méthode qui fonctionne très bien, mais est rarement mentionné, c'est:utiliser un ORM classe qui fait abstraction de base de données spécifique différences de loin pour vous.par exemplevous pouvez obtenir ces dans PHP (RedBean), Python (Django ORM de la couche, Tempête, SqlAlchemy), Ruby on Rails (ActiveRecord), Le cacao (CoreData)

c'est à direvous pouvez faire ceci:

  1. Charger des données à partir de la source de la base de données à l'aide de l'ORM de la classe.
  2. Stocker les données en mémoire ou sérialiser sur le disque.
  3. Stocker des données dans la base de données de destination à l'aide de l'ORM de la classe.

Autres conseils

Tout le monde semble commence avec un peu de grep et perl expressions et vous sorta plutôt quelque chose qui fonctionne pour votre jeu particulier de données, mais vous n'avez aucune idée si c'est importé les données correctement ou pas.Je suis sérieux surpris que personne ne s'est construite une solide bibliothèque qui peut convertir entre les deux.

Voici une liste de TOUTES les différences dans la syntaxe SQL que je sais à propos entre les deux formats de fichiers:Les lignes commençant par:

  • BEGIN TRANSACTION
  • S'ENGAGER
  • sqlite_sequence
  • CREATE UNIQUE INDEX

ne sont pas utilisés dans MySQL

  • SQLlite utilise CREATE TABLE/INSERT INTO "table_name" et MySQL utilise CREATE TABLE/INSERT INTO table_name
  • MySQL n'utilise pas de guillemets à l'intérieur de la définition de schéma
  • MySQL utilise des apostrophes pour les chaînes à l'intérieur de la INSERT INTO les clauses
  • SQLlite et MySQL ont différentes façons de s'en échapper, chaînes à l'intérieur de INSERT INTO les clauses
  • SQLlite utilise 't' et 'f' pour les booléens, MySQL utilise 1 et 0 (une simple regex pour ce qui peut échouer lorsque vous avez une chaîne de caractères comme:"Je ne, vous don\'t' à l'intérieur de votre INSERT INTO)
  • SQLLite utilise AUTOINCREMENT, MySQL utilise AUTO_INCREMENT

Voici un très de base piraté script perl qui fonctionne pour mon jeu de données et de contrôles pour beaucoup plus de ces conditions que les autres scripts perl que j'ai trouvé sur le web.Nu guarentees qu'il va travailler pour vos données, mais n'hésitez pas à modifier et publier 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_]*)\"(.*)/){
            $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_]*)\"(.*)/){
            $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;
    }
}

Voici un script python, de Shalmanese de la réponse et de l'aide de Alex martelli plus à La traduction de Perl Python

Je fais de la communauté wiki, n'hésitez pas à modifier, et refactoriser tant qu'il ne se casse pas la fonctionnalité (heureusement il nous suffit de revenir) - C'est assez laid, mais fonctionne

utilisation comme (en supposant que le script est appelé à dump_for_mysql.py:

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

Vous pouvez ensuite importer dans mysql

remarque - vous devez ajouter une clé étrangère contraint manuellement depuis sqlite ne fait pas les soutenir

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,

C'est le désordre, parce que les fichiers de vidage de base de données spécifique au fournisseur.

Si vous êtes à l'aide de Rails, un plugin existe pour cela.Lire: http://blog.heroku.com/archives/2007/11/23/yamldb_for_databaseindependent_data_dumps/

Mise à jour

Actuellement maintenu fourche: https://github.com/ludicast/yaml_db

MySQL Workbench (licence GPL) qui se déplace de SQLite très facilement par l'intermédiaire de Base de données de l'assistant de Migration.S'installe sur Windows, Ubuntu, RHEL, Fedora et OS X.

Surpris personne n'a mentionné cela maintenant, mais il y a en fait un outil expressément pour cela.C'est en perl, SQL:Traducteur:http://sqlfairy.sourceforge.net/

Convertit entre la plupart de toute forme de tableaux de données (SQL Différent formats de feuille de calcul Excel), et même fait des diagrammes de votre schéma SQL.

aptitude install sqlfairy libdbd-sqlite3-perl

sqlt -f DBI --dsn dbi:SQLite:../.open-tran/ten-sq.db -t MySQL --add-drop-table > mysql-ten-sq.sql
sqlt -f DBI --dsn dbi:SQLite:../.open-tran/ten-sq.db -t Dumper --use-same-auth > sqlite2mysql-dumper.pl
chmod +x sqlite2mysql-dumper.pl
./sqlite2mysql-dumper.pl --help
./sqlite2mysql-dumper.pl --add-truncate --mysql-loadfile > mysql-dump.sql
sed -e 's/LOAD DATA INFILE/LOAD DATA LOCAL INFILE/' -i mysql-dump.sql

echo 'drop database `ten-sq`' | mysql -p -u root
echo 'create database `ten-sq` charset utf8' | mysql -p -u root
mysql -p -u root -D ten-sq < mysql-ten-sq.sql
mysql -p -u root -D ten-sq < mysql-dump.sql

Je viens juste de passer à travers ce processus, et il y a beaucoup de très bonne aide et de l'information en ce Q/r, mais j'ai trouvé que j'avais de rassembler divers éléments (ainsi que certains des autres Q/As) pour obtenir une solution de travail afin d'assurer une migration réussie.

Cependant, même après la combinaison de l'existant réponses, j'ai trouvé que le script Python n'a pas entièrement fonctionné pour moi car il n'a pas de travail où il y avait de multiples boolean occurrences dans un INSERT.Voir ici pourquoi ce qui était le cas.

Donc, je pensais que je poste mon fusionné réponse ici.Le crédit va à ceux qui ont contribué d'ailleurs, bien sûr.Mais je voulais donner quelque chose en retour, et de sauver les autres temps qui suivent.

Je vais poster le script ci-dessous.Mais d'abord, voici les instructions pour une conversion...

J'ai exécuté le script sur OS X 10.7.5 Lion.Python a travaillé hors de la boîte.

Pour générer la base de données MySQL fichier d'entrée de votre base de données SQLite3, exécutez le script sur vos propres fichiers comme suit,

Snips$ sqlite3 original_database.sqlite3 .dump | python ~/scripts/dump_for_mysql.py > dumped_data.sql

J'ai ensuite copié le résultant dumped_sql.fichier sql sur une machine Linux Ubuntu 10.04.4 LTS où ma base de données MySQL est de résider.

Un autre problème que j'ai eu lors de l'importation de la base de données MySQL fichier a été que certains unicode UTF-8 caractères (plus précisément les guillemets simples) n'ont pas été importés correctement, donc j'ai dû ajouter un interrupteur pour la commande de spécifier l'encodage UTF-8.

La commande qui en résulte pour l'entrée de données dans un flambant neuve vide de base de données MySQL est comme suit:

Snips$ mysql -p -u root -h 127.0.0.1 test_import --default-character-set=utf8 < dumped_data.sql

Laissez cuire le tout, et qui doit être elle!N'oubliez pas de passer au crible vos données, avant et après.

Ainsi, comme l'OP demandé, c'est rapide et facile quand vous savez comment!:-)

En aparté, une chose que je n'étais pas sûr à ce sujet avant que je l'ai regardé dans cette migration, était de savoir si created_at et updated_at valeurs de champ serait préservée - la bonne nouvelle pour moi, c'est qu'ils sont, afin que je puisse migrer mes données de production.

Bonne chance!

Mise à JOUR

Depuis ce commutateur, j'ai remarqué un problème que je n'avais pas remarqué avant.Dans mon application Rails, mon champs de texte sont définis comme des "cordes", et cela se retrouve dans le schéma de base de données.Le processus décrit ici les résultats de ceux-ci étant défini comme VARCHAR(255) dans la base de données MySQL.Cela impose une limite de 255 caractères sur ces tailles de champ - et rien au-delà de cette a été tronquée en mode silencieux lors de l'importation.À l'appui de texte de longueur supérieure à 255, le MySQL schéma devez utiliser l'option "TEXTE" plutôt que VARCHAR(255), je crois.Le processus défini ici ne comprennent pas cette conversion.


Voici la fusion et révisé script Python qui a fonctionné pour mes données:

#!/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 ''); was getting
    # converted (inappropriately) to \');
    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 "?([A-Za-z_]*)"?(.*)', 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)
        line = line.replace('AUTOINCREMENT','AUTO_INCREMENT')
        line = line.replace('UNIQUE','')
        line = line.replace('"','')
    else:
        m = re.search('INSERT INTO "([A-Za-z_]*)"(.*)', line)
        if m:
            line = 'INSERT INTO %s%s\n' % m.groups()
            line = line.replace('"', r'\"')
            line = line.replace('"', "'")
            line = re.sub(r"(?<!')'t'(?=.)", r"1", line)
            line = re.sub(r"(?<!')'f'(?=.)", r"0", line)

    # Add auto_increment if it's 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

    # 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)

    print line,

Probablement le rapide de la façon la plus simple est d'utiliser le sqlite .vidage de la commande, dans ce cas, créer un dump de la base de données exemple.

sqlite3 sample.db .dump > dump.sql

Vous pouvez ensuite (en théorie) l'importer dans la base de données mysql, dans ce cas, la base de données de test sur le serveur de base de données 127.0.0.1, à l'aide de la racine de l'utilisateur.

mysql -p -u root -h 127.0.0.1 test < dump.sql

Je dis en théorie car il y a peu de différences entre les grammaires.

Dans sqlite transactions commencer

BEGIN TRANSACTION;
...
COMMIT;

MySQL utilise juste

BEGIN;
...
COMMIT;

Il y a d'autres problèmes similaires (varchars et des guillemets printemps à l'esprit), mais rien de rechercher et remplacer ne pouvait pas fixer.

Peut-être vous devriez vous demander pourquoi vous êtes la migration, si la performance/ taille de base de données est la question peut-être regarder reoginising le schéma, si le système évolue vers un plus puissant produit ce pourrait être le moment idéal pour planifier l'avenir de vos données.

Si vous utilisez Python/Django, c'est assez facile:

créer deux bases de données dans settings.py (comme ici https://docs.djangoproject.com/en/1.11/topics/db/multi-db/)

ensuite, il suffit de faire comme ceci:

objlist = ModelObject.objects.using('sqlite').all()

for obj in objlist:
    obj.save(using='mysql')

J'ai récemment eu à migrer de MySQL pour JavaDB pour un projet à notre équipe.J'ai trouvé un Bibliothèque Java écrit par Apache appelé DdlUtils que fait ce assez facile.Il fournit une API qui vous permet d'effectuer les opérations suivantes:

  1. Découvrez une base de données de schéma et de l'exporter dans un fichier XML.
  2. Modifier une base de données basée sur ce schéma.
  3. Importer des enregistrements à partir d'un DB à l'autre, en supposant qu'ils ont le même schéma.

Les outils que nous nous sommes retrouvés avec n'étaient pas complètement automatisé, mais ils ont très bien fonctionné.Même si votre application n'est pas en Java, il ne devrait pas être trop difficile à concocter quelques petits outils pour faire une migration.Je pense que j'ai été en mesure de tirer de notre migration avec moins de 150 lignes de code.

Obtenir un dump SQL

moose@pc08$ sqlite3 mySqliteDatabase.db .dump > myTemporarySQLFile.sql

L'importation d'un dump MySQL

Pour l'importation de petites quantités:

moose@pc08$ mysql -u <username> -p
Enter password:
....
mysql> use somedb;
Database changed
mysql> source myTemporarySQLFile.sql;

ou

mysql -u root -p somedb < myTemporarySQLFile.sql

Cela vous demandera un mot de passe.Veuillez noter:Si vous souhaitez saisir votre mot de passe, vous devez le faire SANS l'espace, directement après -p:

mysql -u root -pYOURPASS somedb < myTemporarySQLFile.sql

Pour les plus grandes décharges:

mysqlimport ou d'autres outils d'importation comme BigDump.

BigDump vous donne une barre de progression:

enter image description here

Le script python travaillé après quelques modifications, comme suit:

# Remove "PRAGMA foreign_keys=OFF; from beginning of script
# Double quotes were not removed from INSERT INTO "BaselineInfo" table, check if removed from subsequent tables.  Regex needed A-Z added.
# Removed backticks from CREATE TABLE
# Added replace AUTOINCREMENT with AUTO_INCREMENT
# Removed replacement,
#line = line.replace('"', '`').replace("'", '`')

...

useless_es = [
    'BEGIN TRANSACTION',
    'COMMIT',
    'sqlite_sequence',
    'CREATE UNIQUE INDEX',
    'PRAGMA foreign_keys=OFF',
    ]

...

m = re.search('CREATE TABLE "?([A-Za-z_]*)"?(.*)', 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)
    line = line.replace('AUTOINCREMENT','AUTO_INCREMENT')
    line = line.replace('UNIQUE','')
    line = line.replace('"','')
else:
    m = re.search('INSERT INTO "([A-Za-z_]*)"(.*)', line)
    if m:
        line = 'INSERT INTO %s%s\n' % m.groups()
        line = line.replace('"', r'\"')
        line = line.replace('"', "'")

...

Il n'y a pas besoin de tout script,commande,etc...

vous devez exporter votre base de données sqlite comme un .csv fichier et l'importer dans Mysql à l'aide de phpmyadmin.

Je l'ai utilisé et il a travaillé incroyable...

J'utilise le chargeur de données pour la migration de presque toutes les données, il m'aide à convertir MSSQL, MYSQL, MS access pour MSSQL, mysql, csv chargeur, foxpro et MSSQL vers MS access, MYSQl, CSV, foxpro, etc.De mon point de vue c'est un meilleur Outil de transfert de Données

Télécharger Gratuit : http://www.dbload.com

Basé sur Jims la solution:Rapide et facile de migrer SQLite3 pour MySQL?

sqlite3 your_sql3_database.db .dump | python ./dump.py > your_dump_name.sql
cat your_dump_name.sql | sed '1d' | mysql --user=your_mysql_user --default-character-set=utf8 your_mysql_db -p  

Cela fonctionne pour moi.J'utilise sed juste pour jeter la première ligne, ce qui n'est pas mysql, mais vous pouvez aussi le modifier dump.py script pour lancer cette ligne de loin.

Ha...Je souhaite que j'ai trouvé cette première!Ma réponse à ce post... script pour convertir mysql dump sql de fichier en format qui peut être importé dans sqlite3 db

La combinaison des deux serait exactement ce dont j'avais besoin:


Lorsque la base de données sqlite3 est destiné à être utilisé avec ruby, vous souhaitez peut-être modifier:

tinyint([0-9]*) 

pour:

sed 's/ tinyint(1*) / boolean/g ' |
sed 's/ tinyint([0|2-9]*) / integer /g' |

hélas, cette moitié seulement des œuvres, car même si vous êtes à l'insertion de 1 et de 0 dans un champ booléen, sqlite3 les stocke sous forme de 1 et de 0 de sorte que vous avez à parcourir et de faire quelque chose comme:

Table.find(:all, :conditions => {:column => 1 }).each { |t| t.column = true }.each(&:save)
Table.find(:all, :conditions => {:column => 0 }).each { |t| t.column = false}.each(&:save)

mais il était utile d'avoir le fichier sql à regarder pour trouver toutes les opérations booléennes.

fallino correctement identifié l'emplacement de l'erreur dans le script.J'ai la solution.Le problème, c'est les lignes suivantes:

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')

Le remplacement du modèle (2ème paramètre) dans le re.sous les appels est un "régulier" de la chaîne, de sorte qu'au lieu de \1 l'expansion de la première regexp match, il l'étend à un littéral 0x01.De même, \2 s'étend à 0x02.Par exemple, une ligne contenant:,'t','f', serait remplacé par:<0x01>10<0x02>
(Premier remplacement des changements ,'t', à <0 x 1>1<0x2> Deuxième substitution des changements <0x02>'f', à <0 x 1>0<0 x 1>)

La solution est de changer les chaînes de remplacement par l'ajout d'un " r " préfixe, ou par la fuite de l' \1 et \2 dans la chaîne existante.Depuis une manipulation facile de regexp cordes est une des matières les chaînes sont pour, voici le correctif à l'aide de celles-ci:

line = re.sub(r"([^'])'t'(.)", r"\1THIS_IS_TRUE\2", line)
line = line.replace('THIS_IS_TRUE', '1')
line = re.sub(r"([^'])'f'(.)", r"\1THIS_IS_FALSE\2", line)
line = line.replace('THIS_IS_FALSE', '0')

ce logiciel hors de la boîte - fonctionne pour moi.essayez-le et laissez les autres savent.

https://dbconvert.com/sqlite/mysql/

En outre:

J'ai dû faire une petite modification:en quelque sorte l'auto_increment d'un champ (un champ trouvé de message d'erreur) n'a pas été activé.Donc dans phpmyadmin je vérifie la propriété A_I de ce domaine et il fonctionne complètement.Espérons que cela aide.

Dunn.

J'ai écrit ce script simple dans Python3.Il peut être utilisé comme une classe ou en autonomie script appelé par l'intermédiaire d'un terminal shell.Par défaut, les importations de tous les nombres entiers comme int(11)et les chaînes de caractères comme varchar(300), mais tout ce qui peut être ajustée dans le constructeur ou les arguments du script, respectivement.

NOTE: Il nécessite MySQL Connector/Python 2.0.4 ou supérieur

Voici un lien vers la source sur GitHub si vous trouvez le code ci-dessous difficiles à lire: https://github.com/techouse/sqlite3-to-mysql/blob/master/sqlite3mysql.py

#!/usr/bin/env python3

__author__ = "Klemen Tušar"
__email__ = "techouse@gmail.com"
__copyright__ = "GPL"
__version__ = "1.0.1"
__date__ = "2015-09-12"
__status__ = "Production"

import os.path, sqlite3, mysql.connector
from mysql.connector import errorcode


class SQLite3toMySQL:
    """
    Use this class to transfer an SQLite 3 database to MySQL.

    NOTE: Requires MySQL Connector/Python 2.0.4 or higher (https://dev.mysql.com/downloads/connector/python/)
    """
    def __init__(self, **kwargs):
        self._properties = kwargs
        self._sqlite_file = self._properties.get('sqlite_file', None)
        if not os.path.isfile(self._sqlite_file):
            print('SQLite file does not exist!')
            exit(1)
        self._mysql_user = self._properties.get('mysql_user', None)
        if self._mysql_user is None:
            print('Please provide a MySQL user!')
            exit(1)
        self._mysql_password = self._properties.get('mysql_password', None)
        if self._mysql_password is None:
            print('Please provide a MySQL password')
            exit(1)
        self._mysql_database = self._properties.get('mysql_database', 'transfer')
        self._mysql_host = self._properties.get('mysql_host', 'localhost')

        self._mysql_integer_type = self._properties.get('mysql_integer_type', 'int(11)')
        self._mysql_string_type = self._properties.get('mysql_string_type', 'varchar(300)')

        self._sqlite = sqlite3.connect(self._sqlite_file)
        self._sqlite.row_factory = sqlite3.Row
        self._sqlite_cur = self._sqlite.cursor()

        self._mysql = mysql.connector.connect(
            user=self._mysql_user,
            password=self._mysql_password,
            host=self._mysql_host
        )
        self._mysql_cur = self._mysql.cursor(prepared=True)
        try:
            self._mysql.database = self._mysql_database
        except mysql.connector.Error as err:
            if err.errno == errorcode.ER_BAD_DB_ERROR:
                self._create_database()
            else:
                print(err)
                exit(1)

    def _create_database(self):
        try:
            self._mysql_cur.execute("CREATE DATABASE IF NOT EXISTS `{}` DEFAULT CHARACTER SET 'utf8'".format(self._mysql_database))
            self._mysql_cur.close()
            self._mysql.commit()
            self._mysql.database = self._mysql_database
            self._mysql_cur = self._mysql.cursor(prepared=True)
        except mysql.connector.Error as err:
            print('_create_database failed creating databse {}: {}'.format(self._mysql_database, err))
            exit(1)

    def _create_table(self, table_name):
        primary_key = ''
        sql = 'CREATE TABLE IF NOT EXISTS `{}` ( '.format(table_name)
        self._sqlite_cur.execute('PRAGMA table_info("{}")'.format(table_name))
        for row in self._sqlite_cur.fetchall():
            column = dict(row)
            sql += ' `{name}` {type} {notnull} {auto_increment}, '.format(
                name=column['name'],
                type=self._mysql_string_type if column['type'].upper() == 'TEXT' else self._mysql_integer_type,
                notnull='NOT NULL' if column['notnull'] else 'NULL',
                auto_increment='AUTO_INCREMENT' if column['pk'] else ''
            )
            if column['pk']:
                primary_key = column['name']
        sql += ' PRIMARY KEY (`{}`) ) ENGINE = InnoDB CHARACTER SET utf8'.format(primary_key)
        try:
            self._mysql_cur.execute(sql)
            self._mysql.commit()
        except mysql.connector.Error as err:
            print('_create_table failed creating table {}: {}'.format(table_name, err))
            exit(1)

    def transfer(self):
        self._sqlite_cur.execute("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'")
        for row in self._sqlite_cur.fetchall():
            table = dict(row)
            # create the table
            self._create_table(table['name'])
            # populate it
            print('Transferring table {}'.format(table['name']))
            self._sqlite_cur.execute('SELECT * FROM "{}"'.format(table['name']))
            columns = [column[0] for column in self._sqlite_cur.description]
            try:
                self._mysql_cur.executemany("INSERT IGNORE INTO `{table}` ({fields}) VALUES ({placeholders})".format(
                    table=table['name'],
                    fields=('`{}`, ' * len(columns)).rstrip(' ,').format(*columns),
                    placeholders=('%s, ' * len(columns)).rstrip(' ,')
                ), (tuple(data) for data in self._sqlite_cur.fetchall()))
                self._mysql.commit()
            except mysql.connector.Error as err:
                print('_insert_table_data failed inserting data into table {}: {}'.format(table['name'], err))
                exit(1)
        print('Done!')


def main():
    """ For use in standalone terminal form """
    import sys, argparse
    parser = argparse.ArgumentParser()
    parser.add_argument('--sqlite-file', dest='sqlite_file', default=None, help='SQLite3 db file')
    parser.add_argument('--mysql-user', dest='mysql_user', default=None, help='MySQL user')
    parser.add_argument('--mysql-password', dest='mysql_password', default=None, help='MySQL password')
    parser.add_argument('--mysql-database', dest='mysql_database', default=None, help='MySQL host')
    parser.add_argument('--mysql-host', dest='mysql_host', default='localhost', help='MySQL host')
    parser.add_argument('--mysql-integer-type', dest='mysql_integer_type', default='int(11)', help='MySQL default integer field type')
    parser.add_argument('--mysql-string-type', dest='mysql_string_type', default='varchar(300)', help='MySQL default string field type')
    args = parser.parse_args()

    if len(sys.argv) == 1:
        parser.print_help()
        exit(1)

    converter = SQLite3toMySQL(
        sqlite_file=args.sqlite_file,
        mysql_user=args.mysql_user,
        mysql_password=args.mysql_password,
        mysql_database=args.mysql_database,
        mysql_host=args.mysql_host,
        mysql_integer_type=args.mysql_integer_type,
        mysql_string_type=args.mysql_string_type
    )
    converter.transfer()

if __name__ == '__main__':
    main()

J'ai l'habitude d'utiliser le Exporter/importer des tables fonction de IntelliJ DataGrip.

step 1 step 2 step 3

Vous pouvez voir le progrès dans le coin en bas à droite.

[enter image description here]

Ce script est ok sauf pour ce cas, bien sûr, j'ai rencontré :

INSERT INTO "requestcomparison_stopword" VALUES(149,'f');
INSERT INTO "requestcomparison_stopword" VALUES(420,'t');

Le script doit donner à cette sortie :

INSERT INTO requestcomparison_stopword VALUES(149,'f');
INSERT INTO requestcomparison_stopword VALUES(420,'t');

Mais donne plutôt que de sortie :

INSERT INTO requestcomparison_stopword VALUES(1490;
INSERT INTO requestcomparison_stopword VALUES(4201;

avec de drôles de caractères non-ascii dans le dernier 0 et 1.

Ce n'était pas plus quand j'ai commenté les lignes suivantes du code (43-46), mais d'autres problèmes sont apparus:


    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')

C'est juste un cas particulier, lorsque l'on veut ajouter une valeur à 'f' ou 't', mais je ne suis pas vraiment à l'aise avec les expressions régulières, je voulais juste place ce cas de se faire corriger par quelqu'un.

En tout cas merci beaucoup pour cette pratique de script !!!

Cette solution simple a fonctionné pour moi:

<?php
$sq = new SQLite3( 'sqlite3.db' );

$tables = $sq->query( 'SELECT name FROM sqlite_master WHERE type="table"' );

while ( $table = $tables->fetchArray() ) {
    $table = current( $table );
    $result = $sq->query( sprintf( 'SELECT * FROM %s', $table ) );

    if ( strpos( $table, 'sqlite' ) !== false )
        continue;

    printf( "-- %s\n", $table );
    while ( $row = $result->fetchArray( SQLITE3_ASSOC ) ) {
        $values = array_map( function( $value ) {
            return sprintf( "'%s'", mysql_real_escape_string( $value ) );
        }, array_values( $row ) );
        printf( "INSERT INTO `%s` VALUES( %s );\n", $table, implode( ', ', $values ) );
    }
}

J'ai pris le script Python de https://stackoverflow.com/a/32243979/746459 (ci-dessus) et il fixe pour faire face à notre propre sqlite schémas.Il y avait quelques questions à traiter.

Vous pouvez le trouver dans le contrôle de source ici: https://bitbucket.org/mjogltd/sqlite3mysql

Aussi disponible est la même chose enveloppé comme un Docker de l'image, ici: https://hub.docker.com/r/mjog/sqlite3mysql/ - il est tout à fait utilisable même dans un bureau de Windows.

J'ai vérifié attentivement toutes les réponses dans ce post, ainsi que les réponses dans un autre post La traduction de Perl Python.Pourtant, aucun ne pouvait résoudre mon problème.

Mon scénario est j'ai besoin de migrer une base de données de Trac de sqlite à MySQL, la base de données contient beaucoup de tech-en fonction du contenu du wiki.Donc à l'intérieur de la INSERT INTO valeurs, il pourrait y avoir des instructions SQL comme CREATE TABLE et AUTOINCREMENT.Mais la, ligne par ligne, de remplacement pourrait avoir de mauvaises remplacements là.

Finalement, j'ai écrit mon propre outil à cette fin:

https://github.com/motherapp/sqlite_sql_parser

L'utilisation est relativement simple:

python parse_sqlite_sql.py export.sql

Deux fichiers seront générés: export.sql.schema.sql et export.sql.data.sql.L'un pour la mise à jour de la DB schéma, et l'autre pour la mise à jour de données DB.

On pourrait faire d'autres modifications manuelles sur la DB fichier de schéma à l'aide d'un éditeur de texte, sans se soucier d'en modifier le contenu.

Espèrent qu'elle aide les autres à l'avenir.

echo ".dump" | sqlite3 /tmp/db.sqlite > db.sql

watch out pour CRÉER des instructions

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top