Un moyen simple et rapide de migrer SQLite3 vers MySQL?

Quelqu'un sait comment migrer facilement une base de données SQLite3 vers MySQL?

199
demandé sur Stephen Cox 2008-08-20 23:49:13

25 réponses

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


Une méthode alternative qui fonctionnerait bien mais est rarement mentionnée est: utilisez une classe ORM qui résume les différences spécifiques de base de données loin pour vous. par exemple, vous les obtenez en PHP ( RedBean ), Python (couche ORM de Django, Storm , SqlAlchemy ), rubis sur Rails ( ActiveRecord ), cacao ( CoreData )

c'est à dire que vous pourriez 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 des données en mémoire ou sérialiser sur le disque.
  3. stocker des données dans la destination base de données utilisant la classe ORM.
52
répondu David d C e Freitas 2016-08-27 04:49:54

tout le monde semble commencer avec quelques expressions greps et perl et vous obtenez un peu quelque chose qui fonctionne pour votre ensemble de données particulier, mais vous n'avez aucune idée si elle a importé les données correctement ou pas. Je suis vraiment surpris que personne n'ait construit une bibliothèque solide qui puisse se 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:

  • DÉBUT DE LA TRANSACTION
  • COMMIT
  • sqlite_sequence
  • CRÉER UN INDEX UNIQUE

ne sont pas utilisés en MySQL

  • SQLlite uses CREATE TABLE / INSERT INTO "table_name" and MySQL uses CREATE TABLE/INSERT INTO table_name
  • MySQL n'utilise pas de guillemets dans la définition du schéma
  • MySQL utilise des guillemets simples pour les chaînes Insérer dans les clauses
  • SQLlite et MySQL ont différentes façons d'échapper aux chaînes à L'intérieur insérez dans les clauses
  • SQLlite utilise 't' et 'f' pour booléens, MySQL utilise 1 et 0 (un regex simple pour cela peut échouer lorsque vous avez une chaîne de caractères comme :' je le fais, vous don\'t' à l'intérieur de votre insertion dans)
  • SQLLite uses AUTOINCREMENT, MySQL uses AUTO_ increment

voici un script perl piraté très basique qui fonctionne pour mon ensemble de données et vérifie beaucoup plus de ces conditions que d'Autres scripts perl que j'ai trouvé sur le web. Nu garantit que cela fonctionnera pour vos données mais n'hésitez pas à modifier et 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_]*)\"(.*)/){
            $name = ;
            $sub = ;
            $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 \n";
            $line =~ s/\"/\\"/g;
            $line =~ s/\"/\'/g;
        }else{
            $line =~ s/\'\'/\\'/g;
        }
        $line =~ s/([^\'])\'t\'(.)/THIS_IS_TRUE/g;
        $line =~ s/THIS_IS_TRUE/1/g;
        $line =~ s/([^\'])\'f\'(.)/THIS_IS_FALSE/g;
        $line =~ s/THIS_IS_FALSE/0/g;
        $line =~ s/AUTOINCREMENT/AUTO_INCREMENT/g;
        print $line;
    }
}
96
répondu Shalmanese 2008-09-17 20:49:49

voici un script python, construit à partir de la réponse de Shalmanese et de l'aide d'Alex martelli à traduire Perl en Python

je le fais wiki communautaire, alors s'il vous plaît n'hésitez pas à éditer, et refactor tant qu'il ne casse pas la fonctionnalité (heureusement, nous pouvons juste revenir en arrière) - il est assez laid mais fonctionne

utiliser comme ainsi (en supposant que le script s'appelle 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 des contraintes de clé étrangère manuellement car sqlite ne les supporte pas réellement

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'(.)", "THIS_IS_TRUE", line)
    line = line.replace('THIS_IS_TRUE', '1')
    line = re.sub(r"([^'])'f'(.)", "THIS_IS_FALSE", 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,
46
répondu Jiaaro 2017-05-23 11:47:28

c'est compliqué parce que les fichiers dump sont spécifiques au vendeur de la base de données.

si vous utilisez des Rails, un grand plugin existe pour cela. Lire: http://blog.heroku.com/archives/2007/11/23/yamldb_for_databaseindependent_data_dumps /

mise à Jour

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

22
répondu ryw 2013-06-17 20:47:05

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

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

7
répondu pdxleif 2011-01-19 11:32:17
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
7
répondu Dashamir Hoxha 2011-10-12 22:07:08

je viens de passer par ce processus, et il ya beaucoup de très bonne aide et de l'information dans cette question/réponse, mais j'ai constaté que je devais rassembler divers éléments (plus certains d'autres questions/réponses) pour obtenir une solution de travail afin de migrer avec succès.

cependant, même après avoir combiné les réponses existantes, j'ai trouvé que le script Python ne fonctionnait pas complètement pour moi car il ne fonctionnait pas là où il y avait plusieurs occurrences booléennes dans un INSERT. Voir ici pourquoi c'était le cas.

alors, j'ai pensé Afficher ma réponse fusionnée ici. Le crédit va à ceux qui ont contribué ailleurs, bien sûr. Mais je voulais donner quelque chose en retour, et sauver d'autres temps qui suivent.

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

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

pour générer le fichier D'entrée MySQL à partir de votre base de données SQLite3 existante, 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 alors copié le dumped_sql résultant.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 du fichier MySQL était que certains caractères unicode UTF-8 (en particulier les guillemets simples) n'étaient pas importés correctement, donc j'ai dû ajouter un commutateur à la commande pour spécifier l'encodage UTF-8.

la commande résultante pour introduire les données dans une nouvelle base de données MySQL vide est la suivante:

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

laissez-le cuire, et ça devrait être ça! N'oubliez pas d'examiner vos données, avant et après.

donc, comme demandé par L'OP, c'est rapide et facile, quand on sait comment! :- )

par ailleurs, une chose dont je n'étais pas sûr avant d'examiner cette migration, c'était si les valeurs de champ created_at et updated_at seraient préservées - la bonne nouvelle pour moi est qu'elles le sont, donc je pourrais migrer mes données de production existantes.

bonne chance!

mise à JOUR

depuis que j'ai fait ce commutateur, j'ai remarqué un problème que je n'avais pas remarqué auparavant. Dans mon application Rails, mes champs de texte sont définis comme' string', et ceci va jusqu'au schéma de la base de données. Le processus décrit ici les résultats sont définis comme VARCHAR (255) dans la base de données MySQL. Cela place une limite de 255 caractères sur ces tailles de champ - et tout au-delà de cela a été silencieusement tronqué pendant l'importation. Pour supporter une longueur de texte supérieure à 255, le schéma MySQL devrait utiliser 'TEXT' plutôt que VARCHAR(255), je crois. Le processus défini ici n'inclut pas cette conversion.


voici le script Python fusionné et révisé qui a fonctionné pour mon 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,
7
répondu Snips 2017-05-23 12:02:48

j'ai dû récemment migrer de MySQL à JavaDB pour un projet sur lequel notre équipe travaille. J'ai trouvé une bibliothèque Java écrite par Apache appelée DdlUtils qui rendait cela assez facile. Il fournit une API qui vous permet de faire ce qui suit:

  1. Découvrez le schéma d'une base de données et exportez-le sous forme de fichier XML.
  2. modifier un DB basé sur ce schéma.
  3. importer des enregistrements D'un DB à un autre, en supposant qu'ils ont le même schéma.

les outils avec lesquels nous nous sommes retrouvés n'étaient pas complètement automatisés, mais ils fonctionnaient plutôt bien. 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 pu tirer de notre migration avec moins de 150 lignes de code.

5
répondu Outlaw Programmer 2008-08-21 03:12:51

probablement la manière la plus facile rapide est d'utiliser le sqlite .commande dump, dans ce cas créer un dump de la base de données sample.

sqlite3 sample.db .dump > dump.sql

vous pouvez alors (en théorie) importer ceci 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, en utilisant l'utilisateur root.

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

je dis en théorie car il y a quelques différences entre les grammaires.

Dans sqlite opérations de commencer

BEGIN TRANSACTION;
...
COMMIT;

MySQL utilise juste

BEGIN;
...
COMMIT;

il y a d'autres problèmes similaires (varchars et doubles guillemets reviennent à l'esprit) mais rien trouver et remplacer ne pouvait pas réparer.

peut-être devriez-vous vous demander pourquoi vous migrez, si les performances/ la taille de la base de données est la question peut-être regarder la réorganisation du schéma, si le système se déplace vers un produit plus puissant ce pourrait être le moment idéal pour planifier l'avenir de vos données.

5
répondu Richard Gourlay 2008-08-25 11:10:04

Obtenir un dump SQL

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

Importer un dump MySQL

pour les petites importations:

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

ceci vous demandera un mot de passe. Remarque: Si vous voulez entrer votre mot de passe directement, vous devez le faire sans espace, directement après -p :

mysql -u root -pYOURPASS somedb < myTemporarySQLFile.sql

pour les décharges plus importantes:

mysqlimport ou autre importer des outils comme BigDump .

BigDump vous donne une barre de progression:

enter image description here

5
répondu Martin Thoma 2013-06-22 11:36:51

si vous utilisez Python / Django c'est assez facile:

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

alors faites comme ceci:

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

for obj in objlist:
    obj.save(using='mysql')
5
répondu Mihkorz 2017-07-12 15:32:34

MySQL Workbench (licence GPL) migre de SQLite très facilement via le Database Migration wizard . Installe sur Windows, Ubuntu, RHEL, Fedora et OS X .

4
répondu Patrick Garner 2017-05-15 15:21:11

le script python a fonctionné 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('"', "'")

...

3
répondu Doreen Yen 2015-05-07 12:16:18

j'utilise data loader pour migrer presque toutes les données, il m'aide à convertir MSSQL à MYSQL, MS access à MSSQL, mysql, csv loader, foxpro et MSSQL à MS access, MYSQl, CSV, foxpro etc. À mon avis, Il s'agit d'un meilleur outil de Migration des données

télécharger gratuitement: http://www.dbload.com

2
répondu 2009-08-25 09:12:31

basé sur la solution de Jims: moyen facile et rapide de migrer SQLite3 vers 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  

ça me va. J'utilise sed juste pour lancer la première ligne, ce qui n'est pas mysql-like, mais vous pourriez aussi bien modifier dump.py script pour jeter cette ligne.

2
répondu alekwisnia 2017-05-23 12:02:48

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

combiner les deux serait exactement ce dont j'avais besoin:


lorsque la base de données sqlite3 sera utilisée avec ruby, vous voudrez peut-être changer:

tinyint([0-9]*) 

à:

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

hélas, cela ne fonctionne qu'à moitié parce que même si vous insérez des 1 et des 0 dans un champ booléen marqué, sqlite3 les stocke comme des 1 et des 0 de sorte que vous devez passer et 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.

1
répondu daicoden 2017-05-23 12:26:27

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

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

le schéma de remplacement (2e paramètre) dans le re.sub calls est une chaîne" régulière", donc au lieu de \1 étendre à la première correspondance regexp, elle s'étend à un 0x01 littéral. De même, \2 s'étend à 0x02. Par exemple, une ligne contenant: , 't', 'f', serait remplacé par: <0x01>10 < 0x02>

(La première substitution change, 't', en <0x1>1<0x2> Deuxième substitution des changements <0x02>'f' <0 x 1>0<0 x 1>)

le correctif consiste soit à changer les chaînes de remplacement en ajoutant un préfixe "r", soit à échapper aux \1 et \2 de la chaîne existante. Puisque la manipulation facile des cordes regexp est ce que les cordes brutes sont pour, voici le correctif en utilisant ceux:

line = re.sub(r"([^'])'t'(.)", r"THIS_IS_TRUE", line)
line = line.replace('THIS_IS_TRUE', '1')
line = re.sub(r"([^'])'f'(.)", r"THIS_IS_FALSE", line)
line = line.replace('THIS_IS_FALSE', '0')
1
répondu mxbraun 2012-11-13 12:17:57

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 un petit changement: d'une certaine façon l'auto_increment d'un champ (un champ trouvé de message d'erreur) n'a pas été activé. Ainsi, dans phpmyadmin, je vérifie la propriété A_I de ce champ et cela fonctionne complètement. Espérons que cela aide.

Dunn.

1
répondu Dung 2015-07-23 04:12:23

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

vous devez uniquement exporter votre base de données sqlite en tant que Fichier .csv et ensuite l'importer dans Mysql en utilisant phpmyadmin.

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

1
répondu NavidIvanian 2016-07-16 18:54:15

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 à la place que la sortie :

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

avec quelques étranges caractères non-ascii autour des derniers 0 et 1.

cela n'est plus apparu lorsque j'ai commenté les lignes suivantes du code (43-46) mais d'autres problèmes sont apparus:


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

C'est juste un cas spécial, quand nous voulons ajouter une valeur étant 'f' ou 't' mais je ne suis pas vraiment à l'aise avec les expressions régulières, je voulais juste repérer ce cas pour être corrigé par quelqu'un.

en tout cas merci beaucoup pour ce script pratique !!!

0
répondu 2009-09-30 14:50:54

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 ) );
    }
}
0
répondu soulseekah 2015-11-19 06:41:00

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

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

également disponible est la même chose enveloppé comme une image Docker, ici: https://hub.docker.com/r/mjog/sqlite3mysql / - il est entièrement utilisable même sous un bureau Windows.

0
répondu jmkgreen 2017-05-23 11:54:59

j'ai écrit ce script simple en Python3. Il peut être utilisé comme une classe incluse ou un script autonome invoqué via un terminal shell. Par défaut, il importe tous les entiers comme int(11) et les chaînes comme varchar(300) , mais tout ce qui peut être ajusté dans le constructeur ou script arguments respectivement.

NOTE: il nécessite un connecteur MySQL / Python 2.0.4 ou plus

voici un lien vers la source sur GitHub si vous trouvez le code ci-dessous difficile à 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()
0
répondu techouse 2018-06-08 18:18:50

j'ai soigneusement vérifié toutes les réponses dans ce post, ainsi que les réponses dans un autre post lié traduction Perl en Python . Pourtant, aucun n'a pu résoudre entièrement mon problème.

mon scénario est que je dois migrer une base de données de Trac de sqlite vers MySQL, et la base de données contient beaucoup de contenu wiki basé sur la technologie. Par conséquent, à l'intérieur des valeurs INSERT INTO , il pourrait y avoir des instructions SQL comme CREATE TABLE et AUTOINCREMENT . Mais l' le remplacement ligne par ligne pourrait avoir de mauvais remplacements là-bas.

finalement j'ai écrit mon propre outil à cet effet:

https://github.com/motherapp/sqlite_sql_parser

l'usage 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 . Une pour le schéma DB mis à jour, et l'autre pour les données DB mises à jour.

on pourrait faire d'autres modifications manuelles sur le fichier DB schema en utilisant n'importe quel éditeur de texte, sans se soucier de changer le contenu.

espère qu'il pourrait aider d'autres à l'avenir.

-1
répondu Walty Yeung 2017-05-23 11:47:28
echo ".dump" | sqlite3 /tmp/db.sqlite > db.sql

attention à créer des déclarations

-5
répondu mgribov 2012-10-26 10:12:06