Modo semplice e veloce per migrare SQLite3 su MySQL? [chiuso]


Risposte:


62

Ecco un elenco di convertitori (non aggiornato dal 2011):


Un metodo alternativo che funzionerebbe bene ma che viene raramente menzionato è: utilizzare una classe ORM che elimina le differenze specifiche del database. ad es. ottieni questi in PHP ( RedBean ), Python (layer ORM di Django, Storm , SqlAlchemy ), Ruby on Rails ( ActiveRecord ), Cocoa ( CoreData )

cioè potresti farlo:

  1. Caricare i dati dal database di origine utilizzando la classe ORM.
  2. Archivia i dati in memoria o serializza su disco.
  3. Memorizzare i dati nel database di destinazione utilizzando la classe ORM.

107

Tutti sembrano iniziare con qualche greps ed espressioni perl e in qualche modo ottieni qualcosa che funziona per il tuo particolare set di dati ma non hai idea se i dati siano stati importati correttamente o meno. Sono seriamente sorpreso che nessuno abbia costruito una solida libreria in grado di convertire tra i due.

Ecco un elenco di TUTTE le differenze nella sintassi SQL che conosco tra i due formati di file: Le righe che iniziano con:

  • INIZIA TRANSAZIONE
  • COMMETTERE
  • sqlite_sequence
  • CREA UN INDICE UNICO

non sono usati in MySQL

  • SQLlite utilizza CREATE TABLE/INSERT INTO "table_name" e usi MySQLCREATE TABLE/INSERT INTO table_name
  • MySQL non utilizza le virgolette all'interno della definizione dello schema
  • MySQL utilizza virgolette singole per le stringhe all'interno delle INSERT INTOclausole
  • SQLlite e MySQL hanno diversi modi per sfuggire alle stringhe all'interno delle INSERT INTOclausole
  • SQLlite usa 't'e 'f'per i booleani, MySQL usa 1e 0(una semplice regex per questo può fallire quando hai una stringa come: 'I do, you don \' t 'inside your INSERT INTO)
  • SQLLite utilizza AUTOINCREMENT, MySQL utilizzaAUTO_INCREMENT

Ecco uno script perl hackerato di base che funziona per il mio set di dati e controlla molte altre di queste condizioni che altri script perl ho trovato sul web. Nu garantisce che funzionerà per i tuoi dati, ma sentiti libero di modificare e pubblicare qui.

#! /usr/bin/perl

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

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

8
Alex Martelli fatto un ottimo lavoro di riscrittura questo come pitone sopra a stackoverflow.com/questions/1067060/perl-to-python
Jiaaro

Ho aggiunto lo script Python completo (lo script perl da solo non ha funzionato abbastanza per me ... aveva bisogno di qualche elaborazione extra per gestire le chiavi
esterne

Ho riscritto questa risposta sull'altra domanda stackoverflow.com/questions/1067060/_/1070463#1070463
Brad Gilbert,

2
COMMIT e CREATE UNIQUE INDEX sono comandi MySQL validi, correggili.
Niutech,

5
Capisco che il tuo script sia "rapido e sporco", ma anche molto utile, quindi ecco alcune aggiunte / correzioni di bug: * dopo l' && ($line !~ /CREATE UNIQUE INDEX/)aggiunta && ($line !~ /PRAGMA foreign_keys=OFF/) * il regex corrispondente al nome della tabella manca le cifre, che è invece $line =~ /INSERT INTO \"([a-z_]*)\"(.*)/deve esserci $line =~ /INSERT INTO \"([a-z_1-9]*)\"(.*)/ Spero che questo aiuti il ​​futuro lettori
Michał Leon,

50

Ecco uno script di Python, basato sulla risposta di Shalmanese e un po 'di aiuto da Alex Martelli a Translating Perl in Python

Sto realizzando il wiki della community, quindi sentiti libero di modificarlo e refactoring purché non ne rompa la funzionalità (per fortuna possiamo solo tornare indietro) - È piuttosto brutto ma funziona

usa così (supponendo che lo script si chiami dump_for_mysql.py:

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

Che puoi quindi importare in mysql

nota: è necessario aggiungere manualmente i vincoli di chiave esterna poiché sqlite non li supporta effettivamente

ecco la sceneggiatura:

#!/usr/bin/env python

import re
import fileinput

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

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

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

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

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

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

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

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

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

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

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

    print line,

2
Ciao Jim, nel mio set di dati ogni prima istruzione INSERT è racchiusa in un backquote invece che in una singola citazione: __ DROP TABLE IF EXISTS schema_migrations; CREA TABELLA SE NON ESISTE schema_migrations( versionvarchar (255) NON NULL); INSERISCI IN schema_migrations VALUES ( 20100714032840); INSERIRE VALORI di schema_migrations ('20100714033251'); __
David,

bene ... non appare sopra, ma i backquotes appaiono all'interno dei VALORI ([QUI] 20100714032840 [/ QUI])
David

1
AUTOINCREMENT in Mysql è AUTO_INCREMENT. Lo script non tiene conto di ciò.
giuseppe,

Questo non funziona per un database wiki multimediale. Molti errori: Blobvartipo di dati, tick posteriori
nell'istruzione

1
non funziona Potrebbe non essere preso in considerazione tutte le condizioni ...
Himanshu Bansal

10

Probabilmente il modo più semplice e veloce è usare il comando sqlite .dump, in questo caso creare un dump del database di esempio.

sqlite3 sample.db .dump > dump.sql

È quindi possibile (in teoria) importarlo nel database mysql, in questo caso il database di test sul server di database 127.0.0.1, usando l'utente root.

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

Dico in teoria perché ci sono alcune differenze tra le grammatiche.

In sqlite iniziano le transazioni

BEGIN TRANSACTION;
...
COMMIT;

MySQL usa solo

BEGIN;
...
COMMIT;

Ci sono altri problemi simili (mi vengono in mente varchar e virgolette doppie) ma nulla da trovare e sostituire non può essere risolto.

Forse dovresti chiederti perché stai eseguendo la migrazione, se il problema è rappresentato dalle dimensioni del database / delle prestazioni, forse potresti riconsiderare lo schema, se il sistema si sta spostando su un prodotto più potente, questo potrebbe essere il momento ideale per pianificare il futuro dei tuoi dati.


2
ma il compito più difficile è la differenza tra grammatiche tra due settimane
francois,


8
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

Ho appena completato questo processo e ci sono molti ottimi aiuti e informazioni in questo Q / A, ma ho scoperto che dovevo mettere insieme vari elementi (più alcuni da altri Q / As) per ottenere una soluzione funzionante in per migrare correttamente.

Tuttavia, anche dopo aver combinato le risposte esistenti, ho scoperto che lo script Python non ha funzionato completamente per me in quanto non funzionava in presenza di più occorrenze booleane in un INSERT. Vedi qui perché è stato così.

Quindi, ho pensato di pubblicare qui la mia risposta unita. Il merito va a coloro che hanno contribuito altrove, ovviamente. Ma volevo restituire qualcosa e salvare agli altri il tempo che seguirà.

Pubblicherò lo script qui sotto. Ma prima, ecco le istruzioni per una conversione ...

Ho eseguito lo script su OS X 10.7.5 Lion. Python ha funzionato fuori dagli schemi.

Per generare il file di input MySQL dal tuo database SQLite3 esistente, esegui lo script sui tuoi file come segue,

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

Ho quindi copiato il file dumped_sql.sql risultante su un box Linux con Ubuntu 10.04.4 LTS in cui risiedeva il mio database MySQL.

Un altro problema che avevo durante l'importazione del file MySQL era che alcuni caratteri Unicode UTF-8 (in particolare le virgolette singole) non venivano importati correttamente, quindi ho dovuto aggiungere un interruttore al comando per specificare UTF-8.

Il comando risultante per inserire i dati in un nuovo database MySQL vuoto è il seguente:

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

Lascialo cuocere e dovrebbe essere così! Non dimenticare di controllare i tuoi dati, prima e dopo.

Quindi, come richiesto dall'OP, è facile e veloce sapere come fare! :-)

Per inciso, una cosa di cui non ero sicuro prima di esaminare questa migrazione, era se i valori dei campi create_at e updated_at sarebbero stati preservati: la buona notizia per me è che lo sono, quindi potrei migrare i miei dati di produzione esistenti.

In bocca al lupo!

AGGIORNARE

Da quando ho fatto questo passaggio, ho notato un problema che non avevo notato prima. Nella mia applicazione Rails, i miei campi di testo sono definiti come 'string', e questo porta allo schema del database. Il processo qui delineato comporta la loro definizione come VARCHAR (255) nel database MySQL. Ciò pone un limite di 255 caratteri su queste dimensioni del campo e qualsiasi cosa oltre a ciò è stata troncata silenziosamente durante l'importazione. Per supportare una lunghezza del testo maggiore di 255, credo che lo schema MySQL dovrebbe usare "TEXT" anziché VARCHAR (255). Il processo qui definito non include questa conversione.


Ecco lo script Python unito e rivisto che ha funzionato per i miei dati:

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

1
Grazie. Lo script come attualmente scritto sopra ha un errore di sintassi in esso; "else:" nella riga 41 non è al livello di rientro corretto. Non mi è chiaro se le righe sopra devono essere rientrate o se sta succedendo qualcos'altro. Vuoi aggiornare?
Dan Tenenbaum,

5

Di recente ho dovuto migrare da MySQL a JavaDB per un progetto a cui il nostro team sta lavorando. Ho trovato una libreria Java scritta da Apache chiamata DdlUtils che ha reso tutto abbastanza semplice. Fornisce un'API che ti consente di effettuare le seguenti operazioni:

  1. Scopri lo schema di un database ed esportalo come file XML.
  2. Modifica un DB basato su questo schema.
  3. Importa i record da un DB a un altro, supponendo che abbiano lo stesso schema.

Gli strumenti con cui siamo finiti non erano completamente automatizzati, ma hanno funzionato abbastanza bene. Anche se l'applicazione non è in Java, non dovrebbe essere troppo difficile creare alcuni piccoli strumenti per eseguire una migrazione singola. Penso di essere stato in grado di estrarre la nostra migrazione con meno di 150 righe di codice.


4

Non è necessario alcuno script, comando, ecc ...

devi solo esportare il tuo database sqlite come .csvfile e quindi importarlo in Mysql usando phpmyadmin.

L'ho usato e ha funzionato alla grande ...


In combinazione con questo , questa è l'unica risposta che ha funzionato per me.
cdauth,

3

Basato sulla soluzione di Jims: un modo semplice e veloce per migrare SQLite3 su 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  

Questo funziona per me. Uso sed solo per lanciare la prima riga, che non è simile a mysql, ma potresti anche modificare lo script dump.py per eliminare questa riga.


1
Ho avuto alcuni problemi di codifica UTF-8 con i dati importati, ma l'aggiunta di --default-character-set = utf8 al comando di importazione sembra aver risolto questo problema. Tratto da questo Q / A: stackoverflow.com/questions/346092/…
Snips

Ok, l'ho aggiunto - va bene?
alekwisnia,

Ecco dove sto usando l'interruttore extra, sì.
Taglia il

3

Ottieni un dump SQL

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

Importa dump su MySQL

Per piccole importazioni:

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

o

mysql -u root -p somedb < myTemporarySQLFile.sql

Questo ti chiederà una password. Nota: se si desidera inserire direttamente la password, è necessario farlo SENZA spazio, subito dopo -p:

mysql -u root -pYOURPASS somedb < myTemporarySQLFile.sql

Per discariche più grandi:

mysqlimport o altri strumenti di importazione come BigDump .

BigDump ti dà una barra di avanzamento:

inserisci qui la descrizione dell'immagine


12
Questo non funziona a causa di lievi differenze di sintassi e flag in sqlite vs mysql. Devi ancora convertirlo manualmente.
dlite922,

1

Ah ... Vorrei averlo trovato prima! La mia risposta è stata a questo post ... script per convertire mysql dump file sql in formato che può essere importato in sqlite3 db

Combinare i due sarebbe esattamente quello di cui avevo bisogno:


Quando il database sqlite3 verrà utilizzato con ruby ​​potresti voler cambiare:

tinyint([0-9]*) 

per:

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

ahimè, solo questa metà funziona perché anche se stai inserendo 1 e 0 in un campo contrassegnato come booleano, sqlite3 li memorizza come 1 e 0, quindi devi passare e fare qualcosa del tipo:

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)

ma è stato utile avere il file sql da guardare per trovare tutti i booleani.


1

Ho scritto questo semplice script in Python3. Può essere usato come classe inclusa o script autonomo invocato tramite una shell terminale. Per impostazione predefinita importa tutti i numeri interi come int(11)e stringhe comevarchar(300) , ma tutto ciò che può essere regolato rispettivamente negli argomenti del costruttore o dello script.

NOTA: richiede MySQL Connector / Python 2.0.4 o versioni successive

Ecco un link alla fonte su GitHub se trovi il codice qui sotto difficile da leggere: https://github.com/techouse/sqlite3-to-mysql

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

Questo script è ok tranne questo caso che ovviamente ho incontrato:

INSERISCI IN "requestcomparison_stopword" VALUES (149, 'f');
INSERIRE VALORI "requestcomparison_stopword" (420, 't');

Lo script dovrebbe fornire questo output:

INSERIRE requestcomparison_stopword VALUES (149, 'f');
INSERIRE requestcomparison_stopword VALUES (420, 't');

Ma dà invece quell'output:

INSERIRE requestcomparison_stopword VALUES (1490;
INSERIRE requestcomparison_stopword VALUES (4201;

con alcuni strani caratteri non ascii intorno agli ultimi 0 e 1.

Questo non è più apparso quando ho commentato le seguenti righe del codice (43-46) ma sono comparsi altri problemi:


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

Questo è solo un caso speciale, quando vogliamo aggiungere un valore che sia 'f' o 't' ma non mi sento davvero a mio agio con le espressioni regolari, volevo solo individuare questo caso per essere corretto da qualcuno.

Comunque grazie mille per quella comoda sceneggiatura !!!


0

Questa semplice soluzione ha funzionato per me:

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

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

attenzione alle dichiarazioni CREATE

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.