Pregunta

Alguien sabe de un fácil y rápido a la hora de migrar una base de datos SQLite3 para MySQL?

¿Fue útil?

Solución

Aquí está una lista de convertidores (no se actualiza desde 2011):


Un método alternativo que iba a funcionar muy bien, pero rara vez se menciona es:el uso de un ORM clase que los resúmenes específicos de la base de datos de diferencias de distancia de usted.por ejemplo,usted obtener estas en PHP (RedBean), Python (Django del ORM de la capa, La tormenta, SqlAlchemy), Ruby on Rails (ActiveRecord), Cacao (CoreData)

es decir,usted podría hacer esto:

  1. Carga de datos desde el origen de la base de datos utilizando el ORM de la clase.
  2. Almacenar datos en la memoria o serializar en el disco.
  3. Almacén de datos en la base de datos de destino utilizando el ORM de la clase.

Otros consejos

Parece que todo el mundo comienza con un par de greps y perl expresiones y sorta obtener un poco de algo que funcione para su particular conjunto de datos, pero usted no tiene idea de si es importado los datos correctamente o no.Estoy seriamente sorprendido a nadie construido una sólida biblioteca que puede convertir entre los dos.

Aquí una lista de TODAS las diferencias en la sintaxis de SQL, que yo sepa entre los dos formatos de archivo:Las líneas que comienzan con:

  • BEGIN TRANSACTION
  • COMETER
  • sqlite_sequence
  • CREATE UNIQUE INDEX

no se utilizan en MySQL

  • SQLlite utiliza CREATE TABLE/INSERT INTO "table_name" y utiliza MySQL CREATE TABLE/INSERT INTO table_name
  • MySQL no utilizar comillas dentro de la definición de esquema
  • MySQL usa comillas simples para las cadenas en el interior de la INSERT INTO cláusulas
  • SQLlite y MySQL tienen diferentes maneras de escapar de las cadenas en el interior INSERT INTO cláusulas
  • SQLlite utiliza 't' y 'f' para los booleanos, MySQL usa 1 y 0 (una simple expresión regular que este puede fallar cuando usted tiene una cadena como:'Yo, usted don\'t' en el interior de su INSERT INTO)
  • SQLLite utiliza AUTOINCREMENT, MySQL usa AUTO_INCREMENT

Aquí es muy básico hackeado perl script que funciona para mi conjunto de datos y comprueba que muchas más de estas condiciones que otros scripts de perl que he encontrado en la web.Nu guarentees que va a trabajar para sus datos, pero siéntase libre de modificar y publicar aquí.

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

Aquí está una secuencia de comandos de python, construido fuera de Shalmanese la respuesta y la ayuda de Alex martelli más en La traducción de Perl para Python

Estoy haciendo wiki de la comunidad, así que por favor siéntase libre de editar, y refactorizar el tiempo que no se rompa la funcionalidad (por suerte, podemos revertir) - Es bastante feo, pero funciona

utilizar como así (suponiendo que el script se llama dump_for_mysql.py:

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

Que a continuación, puede importar a mysql

nota - es necesario agregar la clave externa limita manualmente desde sqlite en realidad no los apoyan

aquí está la secuencia de comandos:

#!/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 complicado porque los archivos de volcado de la base de datos de proveedores específicos.

Si usted está usando Rails, un gran plugin existe para esto.Leer: http://blog.heroku.com/archives/2007/11/23/yamldb_for_databaseindependent_data_dumps/

Actualización

En la actualidad mantiene la horquilla: https://github.com/ludicast/yaml_db

MySQL Workbench (licencia GPL) migra desde SQLite muy fácilmente a través de la Base de datos el asistente para la Migración.Se instala en Windows, Ubuntu, red hat enterprise linux, Fedora y OS X.

Sorprendió a nadie menciona esto por ahora, pero en realidad hay una herramienta explícitamente para ello.Es en perl, SQL:Traductor:http://sqlfairy.sourceforge.net/

Convierte entre la mayoría de cualquier forma de tabular los datos (SQL Diferentes formatos de hoja de cálculo de Excel), e incluso hace que los diagramas de su esquema 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

Acabo de ir a través de este proceso, y hay un montón de muy buena ayuda y la información en este P/A, pero me di cuenta de que tenía que reunir varios elementos (además de algunos de los otros Q/Como) para obtener una solución de trabajo para migrar correctamente.

Sin embargo, incluso después de la combinación de las respuestas existentes, he encontrado que la secuencia de comandos de Python no trabajo para mí, ya que no trabajo, donde hubo múltiples booleano ocurrencias en una INSERCIÓN.Ver aquí por qué ese era el caso.

Así que, pensé que había puesto mi fusionado respuesta aquí.El crédito va para aquellos que han contribuido en otros lugares, por supuesto.Pero quería darle algo a cambio, y salvar a los demás el tiempo que siga.

Voy a publicar la siguiente secuencia de comandos.Pero en primer lugar, he aquí las instrucciones para la conversión...

Corrí el script en OS X Lion 10.7.5.Python trabajado fuera de la caja.

Para generar la base de archivo de entrada ya existentes en su base de datos SQLite3, ejecute la secuencia de comandos en su propia archivos de la siguiente manera,

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

Luego copiar el resultado dumped_sql.archivo sql a un cuadro de Linux con Ubuntu 10.04.4 LTS donde mi base de datos MySQL fue a residir.

Otro problema que tenía cuando la importación de MySQL, el archivo fue que algunos unicode UTF-8 caracteres (específicamente comillas simples) no se importan correctamente, así que he tenido que añadir un interruptor para el comando para especificar la codificación UTF-8.

El comando resultante a la entrada de los datos en una azotaina vacío de la nueva base de datos MySQL es el siguiente:

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

Dejar cocer, y eso debe ser!No se olvide de controlar sus datos, antes y después.

Así que, como el OP solicitado, es rápido y fácil, si sabe cómo hacerlo!:-)

Como un aparte, una cosa que yo no estaba seguro acerca de antes de que yo veía en esta migración, era si created_at y updated_at valores de campo pudiera ser preservada - la buena noticia para mí es que son, para que yo pudiera migrar los datos de producción.

Buena suerte!

ACTUALIZACIÓN

Desde hacer este cambio, me he dado cuenta de un problema que yo no había notado antes.En mi aplicación Rails, mis campos de texto se define como 'cadena', y esto los lleva a través del esquema de base de datos.El proceso descrito aquí los resultados en estos definido como VARCHAR(255) en la base de datos MySQL.Esto pone un límite de 255 caracteres en estos tamaños de campo - y nada más allá de esto fue en silencio truncado durante la importación.Para apoyar el texto de longitud mayor que 255, MySQL, el esquema sería necesario el uso de 'TEXTO' en lugar de VARCHAR(255), creo.El proceso definido aquí no se incluyen este tipo de conversión.


Aquí está la fusión y revisado secuencia de comandos de Python que trabajó para mis datos:

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

Probablemente el rápido camino más fácil es usar sqlite .comando dump, en este caso crear un volcado de la base de datos de ejemplo.

sqlite3 sample.db .dump > dump.sql

Luego, puede (en teoría) la importación de esta en la base de datos mysql, en este caso la base de datos de prueba en la base de datos del servidor 127.0.0.1, utilizando el usuario root.

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

Digo en teoría, ya que hay un par de diferencias entre las gramáticas.

En sqlite transacciones comenzar

BEGIN TRANSACTION;
...
COMMIT;

MySQL utiliza sólo

BEGIN;
...
COMMIT;

Hay otros problemas similares (varchars las comillas dobles y la primavera de nuevo a la mente) pero nada de buscar y reemplazar no podía arreglar.

Tal vez debería preguntar por qué va a migrar, si el rendimiento/ tamaño de base de datos es el tema tal vez mirar reoginising el esquema, si el sistema se está moviendo a una más eficaz del producto este puede ser el momento ideal para planificar el futuro de sus datos.

Si usted está usando Python/Django es muy fácil:

crear dos bases de datos en settings.py (como aquí https://docs.djangoproject.com/en/1.11/topics/db/multi-db/)

a continuación, sólo hacer como esta:

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

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

Recientemente he tenido que migrar de MySQL a JavaDB para un proyecto en el que nuestro equipo está trabajando.He encontrado una Biblioteca de Java escrito por Apache llamado DdlUtils lo que hizo que esta bastante fácil.Proporciona una API que le permite hacer lo siguiente:

  1. Descubrir una base de datos del esquema y exportarlo como un archivo XML.
  2. Modificar una base de datos sobre la base de este esquema.
  3. Importación de registros desde una DB a otro, suponiendo que tienen el mismo esquema.

Las herramientas que terminamos con no estaban completamente automatizado, pero funcionaron bastante bien.Incluso si la aplicación no está en Java, que no debería ser demasiado difícil de batir un par de pequeñas herramientas para hacer una migración de una vez.Creo que fue capaz de sacar de nuestra migración con menos de 150 líneas de código.

Obtener un volcado SQL

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

Importación dump de MySQL

Para las pequeñas importaciones:

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

Esto le pedirá una contraseña.Por favor nota:Si desea introducir su contraseña directamente, tienes que hacerlo SIN espacio, directamente después de -p:

mysql -u root -pYOURPASS somedb < myTemporarySQLFile.sql

Para grandes descargas:

mysqlimport u otras herramientas de importación como BigDump.

BigDump le da una barra de progreso:

enter image description here

La secuencia de comandos de python trabajado después de un par de modificaciones de la siguiente manera:

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

...

No hay necesidad de cualquier secuencia de comandos,comandos,etc...

usted sólo tiene que exportar su base de datos sqlite como un .csv archivo y, a continuación, importarlo en Mysql con phpmyadmin.

He utilizado y trabajado increíble...

Yo uso el cargador de datos para la migración de casi cualquier tipo de datos, me ayuda a convertir MSSQL a MYSQL, MS access a MSSQL, mysql, csv cargador, foxpro y MSSQL para MS access, MYSQl, CSV, foxpro, etc.En mi opinión, esta es una mejor Herramienta de Migración de Datos

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

Basado en Jim de la solución:Fácil y rápido a la hora de migrar de SQLite3 para 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  

Esto funciona para mí.Yo uso sed acaba de lanzar la primera línea, que no es de mysql, pero que también podría modificar dump.py script para lanzar esta línea de distancia.

Ja...Ojalá hubiera encontrado este primero!Mi respuesta a este post... script para convertir mysql dump sql archivo en el formato que se pueden importar en sqlite3 db

La combinación de los dos sería exactamente lo que yo necesitaba:


Cuando la base de datos sqlite3 va a ser utilizado con ruby es posible que desee cambiar:

tinyint([0-9]*) 

a:

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

por desgracia, esto sólo la mitad de las obras, porque aunque la inserción de 1's y 0's en un campo marcado boolean, sqlite3 almacena como 1 y 0, de modo que usted tiene que ir a través y hacer 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)

pero era útil tener el archivo sql para mirar a encontrar todos los valores booleanos.

fallino identificado correctamente la ubicación del error en el script.Tengo la solución.El problema es el siguiente líneas:

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

El modelo de reemplazo (2do parámetro) en el re.sub llamadas es un "normal" de la cadena, así que en lugar de \1 la expansión de la primera regexp partido, que se expande a un literal 0x01.Asimismo, \2 expande a 0x02.Por ejemplo, una línea que contiene:,'t','f', sería reemplazada por:<0x01>10<0x02>
(Primera sustitución cambios ,'t', a <0 x 1>1<0x2> Segunda sustitución cambios <0x02>'f', a <0 x 1>0<0 x 1>)

La solución es cambiar el reemplazo de cadenas de caracteres mediante la adición de una 'r' prefijo, o por escapar de la \1 y \2 en la cadena existente.Desde la manipulación fácil de regexp cadenas es lo que las cadenas crudas, y aquí está la revisión el uso de los:

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

este software fuera de la caja - funciona para mí.probarlo y dejar que los demás sepan.

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

Además:

Tuve que hacer un pequeño cambio:de alguna manera el auto_increment de un campo (un campo encuentra desde el mensaje de error) no estaba habilitado.Así que en phpmyadmin me verificación de la propiedad A_I de este campo y funciona completamente.Espero que ayude.

Dunn.

Escribí este sencillo script en Python3.Puede ser utilizado como un clase o secuencia de comandos independiente invoca a través de una terminal de shell.Por defecto las importaciones de todos los números enteros como int(11)y cadenas como varchar(300), pero todo lo que se puede ajustar en el constructor de secuencia de comandos o argumentos, respectivamente.

NOTA: Se requiere de MySQL Connector/Python 2.0.4 o superior

Aquí hay un enlace a la fuente en GitHub si usted encuentra el siguiente código difícil de leer: 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()

Normalmente yo uso el Exportación/importación de tablas característica de IntelliJ DataGrip.

step 1 step 2 step 3

Usted puede ver el progreso en la esquina inferior derecha.

[enter image description here]

Este script está bien excepto por este caso, que por supuesto, me he encontrado :

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

La secuencia de comandos debe dar a esta salida :

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

Pero da lugar que la salida de :

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

con unos extraños caracteres que no son ascii en torno a los últimos 0 y 1.

Este no aparecen más cuando me comentó las siguientes líneas de código (43-46), pero los problemas de los demás aparecieron:


    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 es sólo un caso especial, cuando se desea añadir un valor 'f' o 't', pero no estoy muy cómodo con expresiones regulares, sólo quería lugar de este caso de ser corregido por alguien.

De todos modos muchas gracias por ese práctico de secuencia de comandos !!!

Esta sencilla solución que funcionó para mí:

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

Me he tomado la secuencia de comandos de Python de https://stackoverflow.com/a/32243979/746459 (arriba) y se fija a lidiar con nuestras propias sqlite esquemas.Hubo un par de temas a tratar.

Usted puede encontrarlo en el control de código fuente aquí: https://bitbucket.org/mjogltd/sqlite3mysql

También disponible es la misma cosa envuelve como una ventana acoplable imagen, aquí: https://hub.docker.com/r/mjog/sqlite3mysql/ - es totalmente utilizable incluso en un escritorio de Windows.

He revisado cuidadosamente todas las respuestas en este post, así como las respuestas en otro post relacionados La traducción de Perl para Python.Sin embargo, ninguno pudo resolver mi problema.

Mi escenario es que necesito migrar una base de datos de Tráco de sqlite a MySQL y la base de datos contiene una gran cantidad de tecnología basada en el contenido del wiki.Por lo tanto, dentro de la INSERT INTO valores, no podía ser de sentencias SQL como CREATE TABLE y AUTOINCREMENT.Pero la línea-por-línea de reemplazo podría tener de malo reemplazos de allí.

Finalmente, he escrito mi propia herramienta para este propósito:

https://github.com/motherapp/sqlite_sql_parser

El uso es relativamente sencillo:

python parse_sqlite_sql.py export.sql

Dos archivos generados: export.sql.schema.sql y export.sql.data.sql.Uno actualizada en el esquema DB, y el otro para actualizar la DB de datos.

Uno podría hacer más modificaciones manuales en el esquema DB archivo con cualquier editor de texto, sin tener que preocuparse de cambiar el contenido.

Espero que podrían ayudar a otros en el futuro.

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

reloj hacia fuera para CREAR declaraciones

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top