Moyen simple et rapide de migrer SQLite3 vers MySQL?

Quelqu’un connaît-il un moyen rapide de migrer une firebase database SQLite3 vers MySQL?

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


    Une autre méthode qui fonctionnerait bien mais qui est rarement mentionnée est la suivante: utilisez une classe ORM qui extrait les différences de firebase database spécifiques pour vous. par exemple, vous les obtenez en PHP ( RedBean ), Python (couche ORM de Django, Storm , SqlAlchemy ), Ruby on Rails ( ActiveRecord ), Cocoa ( CoreData )

    c’est à dire que vous pourriez faire ceci:

    1. Chargez les données de la firebase database source en utilisant la classe ORM.
    2. Stocker des données en mémoire ou sérialiser sur disque.
    3. Stocker les données dans la firebase database de destination à l’aide de la classe ORM.

    Tout le monde semble commencer avec quelques expressions de type “greps” et “perl” et vous obtenez en quelque sorte quelque chose qui fonctionne pour votre jeu de données particulier, mais vous n’avez aucune idée si les données sont imscopes correctement ou non. Je suis sérieusement surpris que personne n’ait construit une bibliothèque solide capable de 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
    • COMMETTRE
    • sqlite_sequence
    • CRÉER UN INDICE UNIQUE

    ne sont pas utilisés dans MySQL

    • SQLlite utilise CREATE TABLE / INSERT INTO “nom_table” et MySQL utilise CREATE TABLE / INSERT INTO nom_table
    • MySQL n’utilise pas de guillemets dans la définition du schéma
    • MySQL utilise des guillemets simples pour les chaînes à l’intérieur des clauses INSERT INTO
    • SQLlite et MySQL ont différentes manières d’échapper des chaînes dans les clauses INSERT INTO
    • SQLlite utilise ‘t’ et ‘f’ pour les booléens, MySQL utilise 1 et 0 (une simple expression rationnelle pour cela peut échouer lorsque vous avez une chaîne comme: ‘je ne sais pas’ dans votre INSERT INTO)
    • SQLLite utilise AUTOINCREMENT, MySQL utilise AUTO_INCREMENT

    Voici un script Perl hacké très basique qui fonctionne pour mon jeu de données et vérifie pour beaucoup d’autres de ces conditions les autres scripts Perl trouvés sur le Web. Nu garantit que cela fonctionnera pour vos données mais n’hésitez pas à les modifier et à les 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 = $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 en python, construit à partir de la réponse de Shalmanese et de l’aide d’Alex Martelli à Translating Perl to Python

    Je suis en train de créer un wiki de communauté, alors n’hésitez pas à le modifier et à le réorganiser tant que cela ne rompt pas la fonctionnalité (heureusement, nous pouvons simplement revenir en arrière) – C’est plutôt moche mais ça marche

    utiliser comme ça (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 append 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'(.)", "\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 désordonné car les fichiers de vidage sont spécifiques aux fournisseurs de bases de données.

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

    Mettre à jour

    Actuellement entretenu fork: https://github.com/ludicast/yaml_db

    Surpris, personne ne l’a mentionné maintenant, mais il y a en fait un outil explicite pour cela. C’est en perl, SQL: Translator: http://sqlfairy.sourceforge.net/

    Convertit la plupart des formes de données tabulaires (différents formats SQL, tableur Excel) et crée même 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 par ce processus, et il y a beaucoup d’aide et d’informations très utiles dans cette Q / R, mais j’ai trouvé que je devais rassembler différents éléments (plus certains autres Q / As) pour obtenir une solution de travail. ordre pour réussir la migration.

    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.

    Donc, j’ai pensé que je publierais ma réponse fusionnée ici. Le crédit va à ceux qui ont consortingbué ailleurs, bien sûr. Mais je voulais donner quelque chose en retour et faire gagner du temps aux autres.

    Je posterai 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é à partir de la boîte.

    Pour générer le fichier d’entrée MySQL à partir de votre firebase database 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 ensuite copié le fichier dumped_sql.sql obtenu sur une machine Linux exécutant Ubuntu 10.04.4 LTS où ma firebase database MySQL devait résider.

    Un autre problème que j’ai rencontré lors de l’importation du fichier MySQL était que certains caractères UTF-8 (en particulier les guillemets simples) n’étaient pas importés correctement. J’ai donc dû append un commutateur à la commande pour spécifier UTF-8.

    La commande résultante pour entrer les données dans une nouvelle firebase database MySQL vide et fessée 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 de scruter vos données avant et après.

    Donc, comme l'OP demandé, c'est rapide et facile, quand vous savez comment! 🙂

    En passant, une chose dont je n'étais pas sûr avant de me pencher sur cette migration, était de savoir si les valeurs des champs created_at et updated_at seraient préservées. La bonne nouvelle est qu'elles le sont, afin de migrer mes données de production existantes.

    Bonne chance!

    METTRE À JOUR

    Depuis ce changement, j'ai remarqué un problème que je n'avais pas remarqué auparavant. Dans mon application Rails, mes champs de texte sont définis en tant que «chaîne», ce qui se répercute sur le schéma de firebase database. Le processus décrit ici est défini comme VARCHAR (255) dans la firebase database MySQL. Cela place une limite de 255 caractères sur ces tailles de champs - et tout ce qui dépasse ce nombre a été 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 pense. Le processus défini ici n'inclut pas cette conversion.


    Voici le script Python fusionné et révisé qui fonctionnait 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"(? 

    J’ai récemment dû migrer de MySQL vers JavaDB pour un projet sur lequel notre équipe travaille. J’ai trouvé une librairie Java écrite par Apache, appelée DdlUtils, qui facilitait grandement la tâche. Il fournit une API qui vous permet d’effectuer les opérations suivantes:

    1. Découvrez le schéma d’une firebase database et exportez-le en tant que fichier XML.
    2. Modifiez une firebase database en fonction de ce schéma.
    3. Importer des enregistrements d’une firebase database à une autre, en supposant qu’ils ont le même schéma.

    Les outils avec lesquels nous nous sums 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 de créer quelques petits outils pour effectuer une migration unique. Je pense que j’ai pu tirer parti de notre migration avec moins de 150 lignes de code.

    Le moyen le plus simple est sans doute d’utiliser la commande sqlite .dump, dans ce cas, créez une sauvegarde de la firebase database exemple.

     sqlite3 sample.db .dump > dump.sql 

    Vous pouvez ensuite (en théorie) importer ceci dans la firebase database mysql, en l’occurrence la firebase database de test sur le serveur de firebase database 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 qu'il y a quelques différences entre les grammaires.

    Les transactions in sqlite commencent

     BEGIN TRANSACTION; ... COMMIT; 

    MySQL utilise juste

     BEGIN; ... COMMIT; 

    Il y a d'autres problèmes similaires (les guillemets et les guillemets doubles reviennent à l'esprit), mais rien ne peut être trouvé et remplacé.

    Peut-être devriez-vous demander pourquoi vous migrez, si la taille des performances / bases de données est peut-être le problème de la réorganisation du schéma, si le système évolue vers un produit plus puissant, cela pourrait être le moment idéal pour planifier vos données.

    Obtenir un vidage SQL

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

    Importation de la sauvegarde sur MySQL

    Pour les petites importations:

     moose@pc08$ mysql -u  -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. S'il vous plaît noter: 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 des décharges plus grandes:

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

    BigDump vous donne une barre de progression:

    entrer la description de l'image ici

    Si vous utilisez Python / Django, c’est assez simple:

    créer deux bases de données dans 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') 

    MySQL Workbench (licence GPL) migre très facilement de SQLite via l’ assistant de migration de firebase database . S’installe sur Windows, Ubuntu, RHEL, Fedora et OS X.

    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 AZ 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('"', "'") 

    J’utilise un chargeur de données pour la migration de presque toutes les données, cela m’aide à convertir MSSQL en MYSQL, MS access à MSSQL, mysql, csv loader, foxpro et MSSQL à MS access, MYSQl, CSV, foxpro etc. Outil de migration de données

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

    Basé sur la solution de Jims: moyen simple 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 

    Cela fonctionne pour moi. J’utilise sed juste pour lancer la première ligne, qui n’est pas comme mysql, mais vous pouvez aussi modifier le script dump.py pour supprimer cette ligne.

    Ha … J’aurais aimé avoir trouvé ça en premier! Ma réponse a été à ce post … script pour convertir le fichier SQL mysql dump en format pouvant être importé dans sqlite3 db

    Combiner les deux serait exactement ce dont j’avais besoin:


    Lorsque la firebase database sqlite3 va être utilisée avec ruby, vous pouvez modifier:

     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 marqué booléen, sqlite3 les stocke en tant que 1 et 0, vous devez donc 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 à rechercher pour trouver tous les booléens.

    fallino a 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'(.)", "\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 motif de remplacement (2ème paramètre) dans les appels re.sub est une chaîne “régulière”, donc au lieu de \ 1 développer la première correspondance d’expression rationnelle, il se développe en un littéral 0x01. De même, \ 2 se développe à 0x02. Par exemple, une ligne contenant:, ‘t’, ‘f’ serait remplacée par: <0x01> 10 <0x02>
    (La première substitution change, “t”, à <0x1> 1 <0x2> La deuxième substitution change <0x02> ‘f’, à <0x1> 0 <0x1>)

    La solution consiste à modifier les chaînes de remplacement en ajoutant un préfixe «r» ou en échappant les caractères \ 1 et \ 2 de la chaîne existante. Étant donné que la manipulation simple des chaînes d’expressions rationnelles correspond à l’utilisation des chaînes brutes, voici le correctif qui utilise ces chaînes:

     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 faites-le savoir.

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

    En outre:

    J’ai dû faire un petit changement: d’une manière ou d’une autre, l’incrémentation automatique d’un champ (un champ trouvé à partir d’un message d’erreur) n’était pas activé. Donc, dans phpmyadmin, je vérifie la propriété A_I de ce champ et cela fonctionne complètement. J’espère que cela aide.

    Dunn.

    Il n’y a pas besoin de script, commande, etc …

    Vous devez uniquement exporter votre firebase database sqlite en tant que fichier .csv , puis l’importer dans Mysql à l’aide de phpmyadmin.

    Je l’ai utilisé et ça a marché incroyable …

    Ce script est correct 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 devrait donner cette sortie:

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

    Mais donne plutôt cette sortie:

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

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

    Cela ne s’est plus montré 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') 

    Ceci est juste un cas particulier, quand on veut append une valeur comme ‘f’ ou ‘t’ mais que je ne suis pas vraiment à l’aise avec les expressions régulières, je voulais juste voir ce cas à corriger par quelqu’un.

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

    Cette solution simple a fonctionné pour moi:

     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_ssortingng( $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 l’ai corrigé pour faire face à nos propres schémas sqlite. Il y avait quelques problèmes à traiter.

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

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

    J’ai écrit ce script simple dans Python3. Il peut être utilisé comme une classe incluse ou un script autonome appelé via un shell de terminal. Par défaut, il importe tous les entiers comme int(11) et les chaînes de caractères comme varchar(300) , mais tout cela peut être ajusté dans les arguments de constructeur ou de script, respectivement.

    REMARQUE: MySQL Connector / Python 2.0.4 ou supérieur est requirejs

    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__ = "[email protected]" __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_ssortingng_type = self._properties.get('mysql_ssortingng_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_ssortingng_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)).rssortingp(' ,').format(*columns), placeholders=('%s, ' * len(columns)).rssortingp(' ,') ), (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-ssortingng-type', dest='mysql_ssortingng_type', default='varchar(300)', help='MySQL default ssortingng 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_ssortingng_type=args.mysql_ssortingng_type ) converter.transfer() if __name__ == '__main__': main() 

    J’ai soigneusement vérifié toutes les réponses dans cet article, ainsi que les réponses dans une autre publication connexe Translating Perl to Python . Pourtant, aucun ne pouvait résoudre complètement mon problème.

    Mon scénario est que je dois migrer une firebase database de Trac de sqlite vers MySQL, et la firebase database contient beaucoup de contenu wiki basé sur la technologie. Par conséquent, dans les valeurs INSERT INTO , il pourrait y avoir des instructions SQL telles que CREATE TABLE et AUTOINCREMENT . Mais le remplacement ligne par ligne pourrait avoir de mauvais remplacements.

    Finalement, j’ai écrit mon propre outil à cet effet:

    https://github.com/motherapp/sqlite_sql_parser

    L’utilisation est relativement simple:

    python parse_sqlite_sql.py export.sql

    Deux fichiers seraient générés: export.sql.schema.sql et export.sql.data.sql . Un pour le schéma de firebase database mis à jour et l’autre pour les données de firebase database mises à jour.

    On pourrait faire d’autres modifications manuelles sur le fichier de schéma de firebase database en utilisant n’importe quel éditeur de texte, sans se soucier de modifier le contenu.

    J’espère que cela pourrait aider les autres à l’avenir.

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

    attention aux instructions CREATE