Maneira rápida e fácil de migrar o SQLite3 para o MySQL? [fechadas]

224

Alguém conhece uma maneira rápida e fácil de migrar um banco de dados SQLite3 para o MySQL?

Stephen Cox
fonte

Respostas:

62

Aqui está uma lista de conversores (não atualizados desde 2011):


Um método alternativo que funcionaria bem, mas raramente é mencionado, é: use uma classe ORM que abstraia diferenças específicas de banco de dados para você. por exemplo, você os obtém em PHP ( RedBean ), Python (camada ORM do Django, Storm , SqlAlchemy ), Ruby on Rails ( ActiveRecord ), Cocoa ( CoreData )

ou seja, você pode fazer isso:

  1. Carregue dados do banco de dados de origem usando a classe ORM.
  2. Armazene dados na memória ou serialize em disco.
  3. Armazene dados no banco de dados de destino usando a classe ORM.
David d C e Freitas
fonte
107

Todo mundo parece começar com algumas expressões greps e perl e você meio que obtém algo que funciona para o seu conjunto de dados específico, mas você não tem idéia se importou os dados corretamente ou não. Estou seriamente surpreso que ninguém tenha construído uma biblioteca sólida que possa ser convertida entre os dois.

Aqui está uma lista de TODAS as diferenças na sintaxe SQL que eu conheço entre os dois formatos de arquivo: As linhas começando com:

  • COMEÇAR A TRANSAÇÃO
  • COMMIT
  • sqlite_sequence
  • CRIAR ÍNDICE ÚNICO

não são usados ​​no MySQL

  • Usos SQLlite CREATE TABLE/INSERT INTO "table_name"e MySQLCREATE TABLE/INSERT INTO table_name
  • O MySQL não usa aspas dentro da definição de esquema
  • O MySQL usa aspas simples para strings dentro das INSERT INTOcláusulas
  • SQLlite e MySQL têm maneiras diferentes de escapar seqüências de caracteres dentro de INSERT INTOcláusulas
  • O SQLlite usa 't'e 'f'para booleanos, o MySQL usa 1e 0(um regex simples para isso pode falhar quando você tem uma string como: 'eu faço, você não' dentro da sua INSERT INTO)
  • SQLLite usa AUTOINCREMENT, MySQL usaAUTO_INCREMENT

Aqui está um script perl hackeado muito básico, que funciona para o meu conjunto de dados e verifica muito mais dessas condições que outros scripts perl que encontrei na web. A Nu garante que funcionará para seus dados, mas fique à vontade para modificar e postar aqui.

#! /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;
    }
}
Shalmanese
fonte
8
Alex Martelli fez um ótimo trabalho reescrever isso como python em cima da stackoverflow.com/questions/1067060/perl-to-python
Jiaaro
Eu adicionei o script python completo (o script perl sozinho não muito trabalho para mim ... precisava de algum processamento extra para lidar com chaves estrangeiras e índices)
Jiaaro
Eu reescrevi esta resposta sobre a outra questão stackoverflow.com/questions/1067060/_/1070463#1070463
Brad Gilbert
2
COMMIT e CREATE UNIQUE INDEX são comandos válidos do MySQL, corrija-o.
Niutech 6/06
5
Entendo que seu script é "rápido e sujo", mas também é muito útil, então, aqui estão algumas adições / correções de bugs: * depois de && ($line !~ /CREATE UNIQUE INDEX/)adicionar && ($line !~ /PRAGMA foreign_keys=OFF/) * a regex de correspondência de nome de tabela perde dígitos, ou seja, em vez de $line =~ /INSERT INTO \"([a-z_]*)\"(.*)/deve haver $line =~ /INSERT INTO \"([a-z_1-9]*)\"(.*)/ Espero que isso ajude o futuro leitores
Michał Leon
50

Aqui está um script python, construído com base na resposta de Shalmanese e com alguma ajuda de Alex martelli em Traduzindo Perl para Python

Eu estou criando o wiki da comunidade, então fique à vontade para editar e refatorar, contanto que não quebre a funcionalidade (felizmente, podemos reverter) - É muito feio, mas funciona

utilização como assim (assumindo que o script é chamado dump_for_mysql.py:

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

Que você pode importar para o mysql

note - você precisa adicionar restrições de chave estrangeira manualmente, pois o sqlite realmente não as suporta

aqui está o 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,
Jiaaro
fonte
2
Olá Jim, no meu conjunto de dados, cada primeira instrução INSERT é agrupada por uma citação retroativa em vez de uma única citação: __ DROP TABLE IF EXISTS schema_migrations; CRIAR TABELA SE NÃO EXISTIR schema_migrations( versionvarchar (255) NÃO NULL); INSERIR EM schema_migrations VALUES ( 20100714032840); INSERIR EM schema_migrations VALUES ('20100714033251'); __
David
bem ... ele não aparece acima, mas as aspas são exibidas dentro de VALUES ([HERE] 20100714032840 [/ HERE])
David
1
O AUTOINCREMENT no Mysql é AUTO_INCREMENT. O script não explica isso.
Giuseppe
Isso não funciona para um banco de dados wiki de mídia. Muitos erros: Blobvartipo de dados, de volta carrapatos na instrução CREATE ...
Frank Hintsch
1
não funciona Pode não ser todas as condições são levados em consideração ...
Himanshu Bansal
10

Provavelmente, a maneira mais rápida e fácil de usar o comando sqlite .dump, nesse caso, crie um despejo do banco de dados de amostra.

sqlite3 sample.db .dump > dump.sql

Você pode (em teoria) importar isso para o banco de dados mysql, nesse caso o banco de dados de teste no servidor de banco de dados 127.0.0.1, usando a raiz do usuário.

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

Eu digo em teoria, pois existem algumas diferenças entre gramáticas.

Nas transações sqlite começam

BEGIN TRANSACTION;
...
COMMIT;

O MySQL usa apenas

BEGIN;
...
COMMIT;

Existem outros problemas semelhantes (varchars e aspas duplas voltam à mente), mas nada que encontrar e substituir não pôde resolver.

Talvez você deva perguntar por que está migrando, se o desempenho / tamanho do banco de dados é o problema, talvez tente reoginizar o esquema, se o sistema estiver migrando para um produto mais poderoso, esse pode ser o momento ideal para planejar o futuro de seus dados.

Richard Gourlay
fonte
2
mas a tarefa mais difícil é a gramáticas diferença betweek
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
Dashamir Hoxha
fonte
7

Acabei de passar por esse processo e há muita ajuda e informações muito boas nesta Perguntas e Respostas, mas descobri que precisava reunir vários elementos (mais alguns de outras perguntas / respostas) para obter uma solução de trabalho. para migrar com sucesso.

No entanto, mesmo depois de combinar as respostas existentes, descobri que o script Python não funcionava totalmente para mim, pois não funcionava onde havia várias ocorrências booleanas em um INSERT. Veja aqui por que esse foi o caso.

Então, pensei em publicar minha resposta mesclada aqui. O crédito vai para aqueles que contribuíram em outros lugares, é claro. Mas eu queria devolver algo e poupar aos outros o tempo que se segue.

Vou postar o script abaixo. Mas, primeiro, aqui estão as instruções para uma conversão ...

Eu executei o script no OS X 10.7.5 Lion. Python trabalhou fora da caixa.

Para gerar o arquivo de entrada MySQL a partir do banco de dados SQLite3 existente, execute o script em seus próprios arquivos da seguinte maneira:

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

Em seguida, copiei o arquivo dumped_sql.sql resultante para uma caixa Linux executando o Ubuntu 10.04.4 LTS onde meu banco de dados MySQL deveria residir.

Outro problema que tive ao importar o arquivo MySQL foi que alguns caracteres UTF-8 unicode (especificamente aspas simples) não estavam sendo importados corretamente, então tive que adicionar uma opção ao comando para especificar UTF-8.

O comando resultante para inserir os dados em um novo banco de dados MySQL vazio é o seguinte:

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

Deixe cozinhar, e deve ser isso! Não se esqueça de examinar seus dados, antes e depois.

Portanto, como o OP solicitou, é rápido e fácil quando você sabe como! :-)

Além disso, uma coisa sobre a qual eu não tinha certeza antes de analisar essa migração era se os valores de campo created_at e updated_at seriam preservados - a boa notícia para mim é que eles são, para que eu pudesse migrar meus dados de produção existentes.

Boa sorte!

ATUALIZAR

Desde que fiz essa alteração, notei um problema que não havia percebido antes. No meu aplicativo Rails, meus campos de texto são definidos como 'string', e isso segue para o esquema do banco de dados. O processo descrito aqui resulta neles sendo definidos como VARCHAR (255) no banco de dados MySQL. Isso coloca um limite de 255 caracteres nesses tamanhos de campo - e qualquer coisa além disso foi truncada silenciosamente durante a importação. Para suportar textos com tamanho superior a 255, o esquema do MySQL precisaria usar 'TEXT' em vez de VARCHAR (255), acredito. O processo definido aqui não inclui essa conversão.


Aqui está o script Python mesclado e revisado que funcionou para meus dados:

#!/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,
Snips
fonte
1
Obrigado. O script, como atualmente escrito acima, possui um erro de sintaxe; o "else:" na linha 41 não está no nível de recuo apropriado. Não está claro para mim se as linhas acima devem ser recuadas ou se algo está acontecendo. Gostaria de atualizar?
Dan Tenenbaum
5

Recentemente, tive que migrar do MySQL para JavaDB para um projeto em que nossa equipe está trabalhando. Encontrei uma biblioteca Java escrita pelo Apache chamada DdlUtils que facilitou bastante isso. Ele fornece uma API que permite fazer o seguinte:

  1. Descubra o esquema de um banco de dados e exporte-o como um arquivo XML.
  2. Modifique um banco de dados com base neste esquema.
  3. Importe registros de um banco de dados para outro, assumindo que eles tenham o mesmo esquema.

As ferramentas com as quais terminamos não eram completamente automatizadas, mas funcionavam muito bem. Mesmo que seu aplicativo não esteja em Java, não deve ser muito difícil preparar algumas ferramentas pequenas para fazer uma migração única. Acho que consegui extrair nossa migração com menos de 150 linhas de código.

Programador foragido
fonte
4

Não há necessidade de nenhum script, comando, etc ...

você só precisa exportar seu banco de dados sqlite como um .csvarquivo e depois importá-lo no Mysql usando phpmyadmin.

Eu usei e funcionou incrível ...

NavidIvanian
fonte
Em combinação com isso , esta é a única resposta que funcionou para mim.
Cdauth
3

Baseado na solução de Jims: maneira fácil e rápida de migrar o SQLite3 para o 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  

Isso funciona para mim. Eu uso o sed apenas para lançar a primeira linha, que não é semelhante ao mysql, mas você também pode modificar o script dump.py para jogar essa linha fora.

alekwisnia
fonte
1
Eu tive alguns problemas de codificação UTF-8 com os dados importados, mas adicionar --default-character-set = utf8 ao comando import parece ter corrigido isso. Retirado deste Q / A: stackoverflow.com/questions/346092/…
Snips
Ok, eu adicionei isso - está tudo bem?
alekwisnia
É aí que estou usando o interruptor extra, sim.
Snips
3

Obter um dump SQL

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

Importar despejo para MySQL

Para pequenas importações:

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

Isso solicitará uma senha. Observação: se você quiser digitar sua senha diretamente, precisará fazê-lo SEM espaço, logo após -p:

mysql -u root -pYOURPASS somedb < myTemporarySQLFile.sql

Para lixões maiores:

mysqlimport ou outras ferramentas de importação como o BigDump .

O BigDump oferece uma barra de progresso:

insira a descrição da imagem aqui

Martin Thoma
fonte
12
Isso não funciona devido a pequenas diferenças de sintaxe e sinalizadores no sqlite vs mysql. Você ainda precisa convertê-lo manualmente.
dlite922
1

Ha ... eu gostaria de ter encontrado isso primeiro! Minha resposta foi para este post ... script para converter arquivo sql de despejo mysql em formato que pode ser importado para sqlite3 db

Combinar os dois seria exatamente o que eu precisava:


Quando o banco de dados sqlite3 for usado com o ruby, você poderá alterar:

tinyint([0-9]*) 

para:

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

infelizmente, essa metade só funciona porque mesmo que você esteja inserindo 1 e 0 em um campo marcado como booleano, o sqlite3 os armazena como 1 e 0, para que você tenha que fazer algo como:

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)

mas foi útil ter o arquivo sql para procurar todos os booleanos.

daicoden
fonte
1

Eu escrevi esse script simples em Python3. Ele pode ser usado como uma classe incluída ou um script independente chamado por meio de um shell de terminal. Por padrão, importa todos os números inteiros as int(11)e strings as varchar(300), mas tudo o que pode ser ajustado nos argumentos construtor ou script, respectivamente.

NOTA: Requer o MySQL Connector / Python 2.0.4 ou superior

Aqui está um link para a fonte no GitHub, se você achar o código abaixo difícil de ler: https://github.com/techouse/sqlite3-to-mysql

#!/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_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()
Klemen Tušar
fonte
0

Este script está ok, exceto neste caso que, é claro, eu conheci:

INSERIR EM "requestcomparison_stopword" VALUES (149, 'f');
INSERIR EM "requestcomparison_stopword" VALUES (420, 't');

O script deve fornecer esta saída:

INSERIR EM requestcomparison_stopword VALUES (149, 'f');
INSERIR EM requestcomparison_stopword VALUES (420, 't');

Mas, ao contrário, fornece essa saída:

INSERIR EM requestcomparison_stopword VALUES (1490;
INSERIR EM requestcomparison_stopword VALUES (4201;

com alguns caracteres estranhos não-ascii nos últimos 0 e 1.

Isso não apareceu mais quando eu comentei as seguintes linhas do código (43-46), mas outros problemas apareceram:


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

Este é apenas um caso especial, quando queremos adicionar um valor sendo 'f' ou 't', mas não me sinto muito à vontade com expressões regulares, só queria identificar esse caso para ser corrigido por alguém.

De qualquer forma, muito obrigado por esse script acessível !!!


fonte
0

Esta solução simples funcionou para mim:

<?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 ) );
    }
}
soulseekah
fonte
-5
echo ".dump" | sqlite3 /tmp/db.sqlite > db.sql

cuidado com as instruções CREATE

mgribov
fonte