Frage

Kennt jemand eine schnelle und einfache Möglichkeit, eine SQLite3-Datenbank nach MySQL zu migrieren?

War es hilfreich?

Lösung

Hier ist eine Liste der Konverter (seit 2011 nicht aktualisiert):


Eine alternative Methode, die gut funktionieren würde, aber selten erwähnt wird, ist:Verwenden Sie eine ORM-Klasse, die bestimmte Datenbankunterschiede für Sie abstrahiert.z.B.Sie erhalten diese in PHP (Rote Bohnen), Python (Djangos ORM-Ebene, Sturm, SqlAlchemy), Ruby on Rails (Aktiver Rekord), Kakao (Kerndatei)

d.h.Sie könnten Folgendes tun:

  1. Laden Sie Daten aus der Quelldatenbank mithilfe der ORM-Klasse.
  2. Speichern Sie Daten im Speicher oder serialisieren Sie sie auf der Festplatte.
  3. Speichern Sie Daten mithilfe der ORM-Klasse in der Zieldatenbank.

Andere Tipps

Jeder scheint mit ein paar Greps- und Perl-Ausdrücken zu beginnen und man bekommt irgendwie etwas, das für seinen speziellen Datensatz funktioniert, aber man hat keine Ahnung, ob die Daten korrekt importiert wurden oder nicht.Ich bin ernsthaft überrascht, dass niemand eine solide Bibliothek erstellt hat, die zwischen beiden konvertieren kann.

Hier eine Liste ALLER mir bekannten Unterschiede in der SQL-Syntax zwischen den beiden Dateiformaten:Die Zeilen beginnen mit:

  • TRANSAKTION BEGINNEN
  • BEGEHEN
  • sqlite_sequence
  • ERSTELLEN SIE EINEN EINZIGARTIGEN INDEX

werden in MySQL nicht verwendet

  • SQLlite verwendet CREATE TABLE/INSERT INTO "table_name" und MySQL verwendet CREATE TABLE/INSERT INTO table_name
  • MySQL verwendet in der Schemadefinition keine Anführungszeichen
  • MySQL verwendet einfache Anführungszeichen für Zeichenfolgen innerhalb von INSERT INTO Klauseln
  • SQLlite und MySQL haben unterschiedliche Möglichkeiten, Zeichenfolgen darin zu maskieren INSERT INTO Klauseln
  • SQLlite verwendet 't' Und 'f' für boolesche Werte verwendet MySQL 1 Und 0 (Ein einfacher regulärer Ausdruck hierfür kann fehlschlagen, wenn Sie eine Zeichenfolge wie diese haben:„Das tue ich, das tust du nicht“ in deinem Inneren INSERT INTO)
  • SQLLite verwendet AUTOINCREMENT, MySQL verwendet AUTO_INCREMENT

Hier ist ein sehr einfaches gehacktes Perl-Skript, das funktioniert Mein Datensatz und prüft auf viele weitere dieser Bedingungen als andere Perl-Skripte, die ich im Web gefunden habe.Nu garantiert, dass es für Ihre Daten funktioniert, Sie können es aber jederzeit ändern und hier veröffentlichen.

#! /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;
    }
}

Hier ist ein Python-Skript, das auf Shalmaneses Antwort und etwas Hilfe von Alex Martelli basiert Perl in Python übersetzen

Ich mache es zu einem Community-Wiki, also zögern Sie nicht, es zu bearbeiten und umzugestalten, solange es die Funktionalität nicht beeinträchtigt (zum Glück können wir einfach ein Rollback durchführen) – es ist ziemlich hässlich, funktioniert aber

so verwenden (vorausgesetzt, das Skript wird aufgerufen dump_for_mysql.py:

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

Was Sie dann in MySQL importieren können

Hinweis: Sie müssen Fremdschlüsseleinschränkungen manuell hinzufügen, da SQLite diese nicht wirklich unterstützt

hier ist das Skript:

#!/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,

Es ist chaotisch, weil Dump-Dateien datenbankspezifisch sind und herstellerspezifisch sind.

Wenn Sie Rails verwenden, gibt es hierfür ein großartiges Plugin.Lesen: http://blog.heroku.com/archives/2007/11/23/yamldb_for_databaseindependent_data_dumps/

Aktualisieren

Derzeit gepflegter Fork: https://github.com/ludicast/yaml_db

MySQL Workbench (GPL-Lizenz) lässt sich sehr einfach von SQLite migrieren über Assistent für die Datenbankmigration.Installiert auf Windows, Ubuntu, RHEL, Fedora und OS X.

Überrascht, dass dies bisher noch niemand erwähnt hat, aber es gibt tatsächlich ein Tool, das explizit dafür vorgesehen ist.Es ist in Perl, SQL:Translator:http://sqlfairy.sourceforge.net/

Konvertiert die meisten Arten von Tabellendaten (verschiedene SQL-Formate, Excel-Tabellen) und erstellt sogar Diagramme Ihres SQL-Schemas.

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

Ich habe diesen Prozess gerade durchlaufen und in dieser Frage/Antwort gibt es viele sehr gute Hilfen und Informationen, aber ich habe festgestellt, dass ich verschiedene Elemente (plus einige aus anderen Fragen/Antworten) zusammenführen musste, um eine funktionierende Lösung zu finden um die Migration erfolgreich durchzuführen.

Selbst nach der Kombination der vorhandenen Antworten stellte ich jedoch fest, dass das Python-Skript für mich nicht vollständig funktionierte, da es nicht funktionierte, wenn in einem INSERT mehrere boolesche Vorkommen auftraten.Sehen Hier warum das so war.

Deshalb dachte ich, ich poste meine zusammengeführte Antwort hier.Der Dank geht natürlich an diejenigen, die an anderer Stelle einen Beitrag geleistet haben.Aber ich wollte etwas zurückgeben und anderen Zeit sparen.

Ich werde das Skript unten veröffentlichen.Aber zunächst einmal die Anleitung für einen Umbau...

Ich habe das Skript unter OS X 10.7.5 Lion ausgeführt.Python funktionierte sofort.

Um die MySQL-Eingabedatei aus Ihrer vorhandenen SQLite3-Datenbank zu generieren, führen Sie das Skript wie folgt für Ihre eigenen Dateien aus:

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

Anschließend habe ich die resultierende Datei dumped_sql.sql auf eine Linux-Box mit Ubuntu 10.04.4 LTS kopiert, auf der sich meine MySQL-Datenbank befinden sollte.

Ein weiteres Problem, das ich beim Importieren der MySQL-Datei hatte, war, dass einige Unicode-UTF-8-Zeichen (insbesondere einfache Anführungszeichen) nicht korrekt importiert wurden, sodass ich dem Befehl einen Schalter hinzufügen musste, um UTF-8 anzugeben.

Der resultierende Befehl zur Eingabe der Daten in eine völlig neue, leere MySQL-Datenbank lautet wie folgt:

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

Lass es kochen, und das sollte es sein!Vergessen Sie nicht, Ihre Daten vorher und nachher zu prüfen.

Also, wie vom OP gefordert, geht es schnell und einfach, wenn man weiß wie!:-)

Abgesehen davon war ich mir nicht sicher, bevor ich mich mit dieser Migration befasste, ob die Feldwerte „created_at“ und „update_at“ erhalten bleiben würden – die gute Nachricht für mich ist, dass dies der Fall ist, sodass ich meine vorhandenen Produktionsdaten migrieren konnte.

Viel Glück!

AKTUALISIEREN

Seit ich diesen Wechsel vorgenommen habe, ist mir ein Problem aufgefallen, das mir vorher nicht aufgefallen war.In meiner Rails-Anwendung sind meine Textfelder als „String“ definiert, und dies wird auf das Datenbankschema übertragen.Der hier beschriebene Prozess führt dazu, dass diese in der MySQL-Datenbank als VARCHAR(255) definiert werden.Dadurch sind diese Feldgrößen auf 255 Zeichen begrenzt – und alles, was darüber hinausgeht, wurde beim Import stillschweigend abgeschnitten.Um Textlängen von mehr als 255 zu unterstützen, müsste das MySQL-Schema meines Erachtens „TEXT“ anstelle von VARCHAR(255) verwenden.Der hier definierte Prozess umfasst diese Konvertierung nicht.


Hier ist das zusammengeführte und überarbeitete Python-Skript, das für meine Daten funktioniert hat:

#!/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,

Der schnellste und einfachste Weg ist wahrscheinlich die Verwendung des Befehls sqlite .dump. In diesem Fall erstellen Sie einen Dump der Beispieldatenbank.

sqlite3 sample.db .dump > dump.sql

Sie können dies dann (theoretisch) mit dem Benutzer root in die MySQL-Datenbank importieren, in diesem Fall die Testdatenbank auf dem Datenbankserver 127.0.0.1.

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

Ich sage theoretisch, da es einige Unterschiede zwischen den Grammatiken gibt.

In SQLite beginnen Transaktionen

BEGIN TRANSACTION;
...
COMMIT;

MySQL verwendet einfach

BEGIN;
...
COMMIT;

Es gibt andere ähnliche Probleme (Varchars und doppelte Anführungszeichen fallen mir ein), aber nichts, was durch Suchen und Ersetzen nicht behoben werden könnte.

Vielleicht sollten Sie sich fragen, warum Sie migrieren. Wenn die Leistung/Datenbankgröße das Problem ist, sollten Sie vielleicht das Schema neu erstellen. Wenn das System auf ein leistungsfähigeres Produkt umsteigt, ist dies möglicherweise der ideale Zeitpunkt, um die Zukunft Ihrer Daten zu planen.

Wenn Sie Python/Django verwenden, ist es ziemlich einfach:

Erstellen Sie zwei Datenbanken in Settings.py (wie hier). https://docs.djangoproject.com/en/1.11/topics/db/multi-db/)

dann mach einfach so:

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

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

Ich musste kürzlich für ein Projekt, an dem unser Team arbeitet, von MySQL auf JavaDB migrieren.Ich habe einen ... gefunden Von Apache geschriebene Java-Bibliothek namens DdlUtils das machte es ziemlich einfach.Es stellt eine API bereit, mit der Sie Folgendes tun können:

  1. Entdecken Sie das Schema einer Datenbank und exportieren Sie es als XML-Datei.
  2. Ändern Sie eine Datenbank basierend auf diesem Schema.
  3. Importieren Sie Datensätze von einer Datenbank in eine andere, vorausgesetzt, sie haben dasselbe Schema.

Die Tools, die uns letztendlich zur Verfügung standen, waren nicht vollständig automatisiert, funktionierten aber recht gut.Selbst wenn Ihre Anwendung nicht in Java ist, sollte es nicht allzu schwierig sein, ein paar kleine Tools für eine einmalige Migration bereitzustellen.Ich glaube, ich konnte unsere Migration mit weniger als 150 Zeilen Code durchführen.

Holen Sie sich einen SQL-Dump

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

Dump in MySQL importieren

Für kleine Importe:

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

oder

mysql -u root -p somedb < myTemporarySQLFile.sql

Dadurch werden Sie zur Eingabe eines Passworts aufgefordert.Bitte beachten Sie:Wenn Sie Ihr Passwort direkt eingeben möchten, müssen Sie dies direkt im Anschluss OHNE Leerzeichen tun -p:

mysql -u root -pYOURPASS somedb < myTemporarySQLFile.sql

Für größere Deponien:

mysqlimport oder andere Importtools wie BigDump.

BigDump gibt Ihnen einen Fortschrittsbalken:

enter image description here

Das Python-Skript funktionierte nach einigen Modifikationen wie folgt:

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

...

Es ist kein Skript, Befehl usw. erforderlich.

Sie müssen Ihre SQLite-Datenbank nur als exportieren .csv Datei und importieren Sie sie dann mit phpmyadmin in MySQL.

Ich habe es verwendet und es hat fantastisch funktioniert ...

Ich verwende den Data Loader zum Migrieren fast aller Daten. Er hilft mir, MSSQL in MYSQL, MS Access in MSSQL, MySQL, CSV Loader, FoxPro und MSSQL in MS Access, MYSQL, CSV, FoxPro usw. zu konvertieren.Meiner Meinung nach ist dies das beste Datenmigrationstool

Gratis herunterladen : http://www.dbload.com

Basierend auf Jims' Lösung:Schnelle und einfache Möglichkeit, SQLite3 nach MySQL zu migrieren?

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  

Das funktioniert bei mir.Ich verwende sed nur, um die erste Zeile auszuwerfen, was nicht MySQL-ähnlich ist, aber Sie können das Skript dump.py genauso gut ändern, um diese Zeile wegzuwerfen.

Ha...Ich wünschte, ich hätte das zuerst gefunden!Meine Antwort war auf diesen Beitrag... Skript zum Konvertieren der MySQL-Dump-SQL-Datei in ein Format, das in die SQLite3-Datenbank importiert werden kann

Die Kombination der beiden wäre genau das, was ich brauchte:


Wenn die SQLite3-Datenbank mit Ruby verwendet werden soll, möchten Sie möglicherweise Folgendes ändern:

tinyint([0-9]*) 

Zu:

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

Leider funktioniert dies nur zur Hälfte, denn obwohl Sie Einsen und Nullen in ein mit boolean markiertes Feld einfügen, speichert sqlite3 sie als Einsen und Nullen, sodass Sie Folgendes tun müssen:

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)

Es war jedoch hilfreich, die SQL-Datei zum Durchsuchen zu haben, um alle booleschen Werte zu finden.

Fallino hat den Ort des Fehlers im Skript korrekt identifiziert.Ich habe die Lösung.Das Problem sind die folgenden Zeilen:

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

Das Ersetzungsmuster (2. Parameter) in den re.sub-Aufrufen ist eine „normale“ Zeichenfolge, sodass \1 nicht auf die erste reguläre Ausdrucksübereinstimmung erweitert wird, sondern auf ein Literal 0x01.Ebenso wird \2 auf 0x02 erweitert.Zum Beispiel eine Zeile mit:, 't', 'f', würde ersetzt durch:10
(Erste Substitution ändert sich, 't', zu <0x1> 1 <0x2> Zweite Substitution Änderungen <0x02> 'f', zu <0x1> 0 <0x1>)

Die Lösung besteht darin, entweder die Ersatzzeichenfolgen durch Hinzufügen eines „r“-Präfixes oder durch Escapezeichen für \1 und \2 in der vorhandenen Zeichenfolge zu ändern.Da es sich bei Rohzeichenfolgen um die einfache Manipulation von regulären Ausdruckszeichenfolgen handelt, finden Sie hier die Lösung, die diese verwendet:

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

Diese Software ist sofort einsatzbereit und funktioniert bei mir.Probieren Sie es aus und lassen Sie es andere wissen.

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

Zusätzlich:

Ich musste eine kleine Änderung vornehmen:Irgendwie wurde die automatische Erhöhung eines Felds (ein in der Fehlermeldung gefundenes Feld) nicht aktiviert.Also überprüfe ich in phpmyadmin die Eigenschaft A_I dieses Felds und es funktioniert vollständig.Ich hoffe es hilft.

Dunn.

Ich habe dieses einfache Skript in Python3 geschrieben.Es kann als integrierte Klasse oder als eigenständiges Skript verwendet werden, das über eine Terminal-Shell aufgerufen wird.Standardmäßig werden alle Ganzzahlen importiert als int(11)und Saiten als varchar(300), aber all das kann in den Konstruktor- bzw. Skriptargumenten angepasst werden.

NOTIZ: Es erfordert MySQL Connector/Python 2.0.4 oder höher

Hier ist ein Link zur Quelle auf GitHub, falls Sie den folgenden Code schwer lesbar finden: 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()

Normalerweise verwende ich das Tabellen exportieren/importieren Merkmal von IntelliJ DataGrip.

step 1 step 2 step 3

Sie können den Fortschritt in der unteren rechten Ecke sehen.

[enter image description here]

Dieses Skript ist in Ordnung, außer in diesem Fall, den ich natürlich getroffen habe:

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

Das Skript sollte diese Ausgabe liefern:

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

Gibt aber stattdessen die Ausgabe:

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

mit einigen seltsamen Nicht-ASCII-Zeichen um die letzte 0 und 1.

Dies wurde nicht mehr angezeigt, als ich die folgenden Codezeilen (43-46) kommentierte, aber es traten andere Probleme auf:


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

Dies ist nur ein Sonderfall, wenn wir einen Wert hinzufügen möchten, der „f“ oder „t“ ist, ich aber mit regulären Ausdrücken nicht wirklich vertraut bin. Ich wollte diesen Fall nur erkennen, damit er von jemandem korrigiert wird.

Trotzdem vielen Dank für das praktische Skript!!!

Diese einfache Lösung hat bei mir funktioniert:

<?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 ) );
    }
}

Ich habe das Python-Skript übernommen https://stackoverflow.com/a/32243979/746459 (oben) und es korrigiert, um mit unseren eigenen SQLite-Schemas zurechtzukommen.Es gab ein paar Probleme zu lösen.

Sie finden es möglicherweise hier in der Quellcodeverwaltung: https://bitbucket.org/mjogltd/sqlite3mysql

Das Gleiche ist auch als Docker-Image verpackt, hier: https://hub.docker.com/r/mjog/sqlite3mysql/ - Es ist auch unter einem Windows-Desktop voll nutzbar.

Ich habe alle Antworten in diesem Beitrag sowie die Antworten in einem anderen verwandten Beitrag sorgfältig geprüft Perl in Python übersetzen.Dennoch konnte keiner mein Problem vollständig lösen.

Mein Szenario sieht so aus, dass ich eine Trac-Datenbank von SQLite nach MySQL migrieren muss und die Datenbank viele technologiebasierte Wiki-Inhalte enthält.Daher innerhalb der INSERT INTO Werte, es könnte SQL-Anweisungen geben wie CREATE TABLE Und AUTOINCREMENT.Aber die zeilenweise Ersetzung könnte dort zu falschen Ersetzungen führen.

Schließlich habe ich zu diesem Zweck mein eigenes Tool geschrieben:

https://github.com/motherapp/sqlite_sql_parser

Die Verwendung ist relativ einfach:

python parse_sqlite_sql.py export.sql

Es würden zwei Dateien generiert: export.sql.schema.sql Und export.sql.data.sql.Eine für das aktualisierte DB-Schema und die andere für aktualisierte DB-Daten.

Man könnte mit jedem Texteditor weitere manuelle Änderungen an der DB-Schemadatei vornehmen, ohne sich Gedanken über die Änderung des Inhalts machen zu müssen.

Ich hoffe, es könnte in Zukunft anderen helfen.

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

Achten Sie auf CREATE-Anweisungen

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top