SQLite3'ü MySQL'e taşımanın hızlı ve kolay yolu? [kapalı]


Yanıtlar:


62

Dönüştürücülerin listesi (2011'den beri güncellenmemiştir):


Güzel çalışan ancak nadiren bahsedilen alternatif bir yöntem şudur: Sizin için belirli veritabanı farklılıklarını soyutlayan bir ORM sınıfı kullanın. bunları PHP ( RedBean ), Python (Django'nun ORM katmanı, Storm , SqlAlchemy ), Ruby on Rails ( ActiveRecord ), Kakao ( CoreData ) ile elde edersiniz

yani bunu yapabilirsin:

  1. ORM sınıfını kullanarak kaynak veritabanından veri yükleyin.
  2. Verileri bellekte saklayın veya diske serileştirin.
  3. ORM sınıfını kullanarak verileri hedef veritabanında depolayın.

107

Herkes birkaç açgözlülük ve perl ifadeleri ile başlıyor gibi görünüyor ve belirli veri kümeniz için işe yarayan bir şey elde etmeniz gerekiyor, ancak verilerin doğru bir şekilde içe aktarılıp aktarılmadığı hakkında hiçbir fikriniz yok. Kimse ikisi arasında dönüştürebilecek sağlam bir kütüphane inşa etmediğine şaşırdım.

Burada iki dosya biçimi arasında bildiğim SQL sözdizimindeki TÜM farklılıkların bir listesi:

  • İŞLEM BAŞLANGIÇ
  • COMMIT
  • sqlite_sequence
  • EŞSİZ DİZİN OLUŞTUR

MySQL'de kullanılmaz

  • SQLlite CREATE TABLE/INSERT INTO "table_name"ve MySQL kullanırCREATE TABLE/INSERT INTO table_name
  • MySQL, şema tanımı içinde tırnak işaretleri kullanmıyor
  • MySQL INSERT INTOdeyimleri içinde dizeler için tek tırnak kullanır
  • SQLlite ve MySQL, INSERT INTOcümlelerin içindeki dizelerden kaçmanın farklı yollarına sahiptir
  • SQLlite kullanır 't've 'f'booleans için, MySQL kullanır 1ve 0(bunun için basit bir regex şöyle bir dizginiz olduğunda başarısız olabilir: ' Yapıyorum , içinde değilsiniz' INSERT INTO)
  • SQLLite kullanır AUTOINCREMENT, MySQL kullanırAUTO_INCREMENT

İşte benim veri kümem için çalışan ve web üzerinde bulduğum diğer perl komut dosyalarının bu koşulların daha fazlasını kontrol eden çok temel bir saldırıya uğramış perl komut dosyası . Nu, verileriniz için çalışacağını ancak burada değişiklik yapmaktan ve geri göndermekten çekinmeyin.

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


Komple python betiğini ekledim (perl betiği benim için pek işe yaramadı ... Yabancı Anahtarları ve Dizinleri işlemek için bazı ekstra işlemlere ihtiyaç duydu)
Jiaaro

Bu cevabı diğer soruya yeniden yazdım stackoverflow.com/questions/1067060/_/1070463#1070463
Brad Gilbert

2
COMMIT ve CREATE UNIQUE INDEX geçerli MySQL komutlarıdır, lütfen düzeltin.
niutech

5
Senaryo "hızlı ve kirli", ama aynı zamanda çok yararlı olduğunu anlıyorum, bu yüzden birkaç ekleme / hata düzeltmeleri: * && ($line !~ /CREATE UNIQUE INDEX/)eklemek sonra && ($line !~ /PRAGMA foreign_keys=OFF/) * tablo adı eşleşen regex basamakları özlüyor, bunun yerine geleceğe yardımcı $line =~ /INSERT INTO \"([a-z_]*)\"(.*)/olacağını $line =~ /INSERT INTO \"([a-z_1-9]*)\"(.*)/umuyoruz okuyucular
Michał Leon

50

İşte Shalmanese cevabı üzerine kurulmuş bir Python komut ve en aşırı Alex Martelli bazı yardımdır Python için Çeviri Perl

Topluluk wiki'sini yapıyorum, bu yüzden lütfen işlevselliği bozmadığı sürece düzenleme ve yeniden düzenleme yapmaktan çekinmeyin (neyse ki geri dönebiliriz) - Oldukça çirkin ama çalışıyor

böyle kullanın (betiğin çağrıldığı varsayılarak dump_for_mysql.py:

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

Hangi mysql içine alabilirsiniz

not - sqlite aslında desteklemediğinden yabancı anahtar kısıtlamalarını manuel olarak eklemeniz gerekir

İşte senaryo:

#!/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
Merhaba Jim, benim veri kümemde her ilk INSERT deyimi tek bir tırnak yerine bir backquote ile sarılır: __ DROP TABLE IF EXISTS schema_migrations; MEVCUT DEĞİLSE TABLO OLUŞTUR schema_migrations( versionvarchar (255) BOŞ DEĞİL); Schema_migrations VALUES ( 20100714032840) içine yerleştirin. Schema_migrations VALUES ('20100714033251') içine yerleştirin; __
David

iyi ... yukarıda görünmüyor, ancak backquotes DEĞERLER içinde görünüyor ([HERE] 20100714032840 [/ HERE])
David

1
Mysql'deki AUTOINCREMENT, AUTO_INCREMENT şeklindedir. Komut dosyası bunu hesaba katmaz.
giuseppe

Bu bir medya wiki veritabanı için çalışmaz. Birçok hata: Blobvarveri türü, CREATE deyiminde geri keneler ...
Frank Hintsch

1
çalışmıyor. Tüm koşullar dikkate alınmayabilir ...
Himanshu Bansal

10

Muhtemelen en kolay yol sqlite .dump komutunu kullanmaktır, bu durumda örnek veritabanının dökümünü oluşturur.

sqlite3 sample.db .dump > dump.sql

Daha sonra bunu (teoride) kullanıcı kökünü kullanarak 127.0.0.1 veritabanı sunucusundaki test veritabanına mysql veritabanına aktarabilirsiniz.

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

Teoride diyorum ki gramerler arasında birkaç fark var.

Sqlite işlemleri başlar

BEGIN TRANSACTION;
...
COMMIT;

MySQL sadece

BEGIN;
...
COMMIT;

Başka benzer sorunlar da var (varchars ve çift tırnak akla geri geliyor) ama hiçbir şey bulmak ve değiştirmek düzeltemedi.

Belki de neden taşıdığınızı sormalısınız, eğer performans / veritabanı boyutu sorunsa, şemayı yeniden tasarlamaya bakın, sistem daha güçlü bir ürüne geçiyorsa, verilerinizin geleceği için planlamak için ideal zaman olabilir.


2
ancak en zor görev gramerler arasındaki farktır
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

Bu süreçten yeni geçtim ve bu Q / A'da çok iyi yardım ve bilgi var, ancak çalışan bir çözüm elde etmek için çeşitli unsurları (artı diğer Q / As'dan bazıları) bir araya getirmem gerektiğini buldum. başarıyla taşındı.

Ancak, mevcut cevapları birleştirdikten sonra bile, bir INSERT'de birden fazla boole olayının olduğu yerde çalışmadığı için Python betiğinin benim için tam olarak çalışmadığını buldum. Bkz burada durum böyle almasının nedeni budur.

Bu yüzden, birleştirilmiş cevabımı buraya göndereceğimi düşündüm. Elbette başka yerlerde katkıda bulunanlara da kredi gidiyor. Ama bir şeyler geri vermek ve diğerlerine bunu takip etmek için zaman kazandırmak istedim.

Aşağıdaki senaryoyu yazacağım. Ama önce, bir dönüşüm için talimatlar ...

Senaryoyu OS X 10.7.5 Lion'da çalıştırdım. Python kutudan çıktı.

MySQL giriş dosyasını mevcut SQLite3 veritabanınızdan oluşturmak için, komut dosyasını kendi dosyalarınızda aşağıdaki gibi çalıştırın,

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

Sonra ortaya çıkan dumped_sql.sql dosyasını MySQL veritabanımın bulunduğu Ubuntu 10.04.4 LTS çalıştıran bir Linux kutusuna kopyaladım.

MySQL dosyasını alırken yaşadığım başka bir sorun, bazı unicode UTF-8 karakterlerinin (özellikle tek tırnak) doğru bir şekilde içe aktarılmamasıydı, bu yüzden UTF-8 belirtmek için komuta bir anahtar eklemek zorunda kaldım.

Veriyi yeni bir boş MySQL veritabanına girmek için ortaya çıkan komut aşağıdaki gibidir:

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

Bırakın pişirin, ve bu olmalı! Önce ve sonra verilerinizi incelemeyi unutmayın.

OP'nin istediği gibi, nasıl olduğunu bildiğinizde hızlı ve kolaydır! :-)

Bir yana, bu geçişe bakmadan önce emin olmadığım bir şey, create_at ve updated_at alan değerlerinin korunup korunmayacağıydı - benim için iyi haber şu ki, mevcut üretim verilerimi taşıyabiliyordum.

İyi şanslar!

GÜNCELLEME

Bu anahtarı yaptığımdan beri, daha önce fark etmediğim bir sorun fark ettim. Rails uygulamamda, metin alanlarım 'dize' olarak tanımlanır ve bu veritabanı şemasına geçer. Burada özetlenen işlem, bunların MySQL veritabanında VARCHAR (255) olarak tanımlanmasına neden olur. Bu, bu alan boyutlarına 255 karakterlik bir sınır koyar ve bunun ötesinde herhangi bir şey içe aktarma sırasında sessizce kesilir. 255'ten büyük metin uzunluğunu desteklemek için, MySQL şemasının VARCHAR (255) yerine 'METİN' kullanması gerektiğine inanıyorum. Burada tanımlanan işlem bu dönüşümü içermez.


Verilerim için çalışan birleştirilmiş ve gözden geçirilmiş Python betiği:

#!/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
Teşekkürler. Şu anda yukarıda yazılı komut dosyasının sözdizimi hatası var; 41 numaralı satırdaki "else:" ifadesi uygun girinti düzeyinde değil. Yukarıdaki çizgilerin girintili olup olmayacağı veya başka bir şeyin olup olmadığı bana açık değil. Güncellemek ister misiniz?
Dan Tenenbaum

5

Son zamanlarda ekibimizin üzerinde çalıştığı bir proje için MySQL'den JavaDB'ye geçmek zorunda kaldım. Apache tarafından yazılan ve bunu oldukça kolaylaştıran DdlUtils adlı bir Java kütüphanesi buldum . Aşağıdakileri yapmanızı sağlayan bir API sağlar:

  1. Bir veritabanının şemasını keşfedin ve XML dosyası olarak dışa aktarın.
  2. Bir DB'yi bu şemaya göre değiştirin.
  3. Aynı şemaya sahip olduklarını varsayarak kayıtları bir DB'den diğerine aktarın.

Sonuçta elde ettiğimiz araçlar tamamen otomatik değildi, ancak oldukça iyi çalıştılar. Uygulamanız Java'da olmasa bile, bir kerelik taşıma yapmak için birkaç küçük aracı kırmak çok zor olmamalıdır. 150'den az kod satırı ile göçümü çekebildiğimi düşünüyorum.


4

Herhangi bir komut dosyasına, komuta vb. Gerek yoktur.

sqlite veritabanınızı sadece bir .csvdosya olarak dışa aktarmanız ve sonra phpmyadmin kullanarak Mysql'e aktarmanız gerekir.

Ben kullandım ve harika çalıştı ...


İle birlikte bu , bu benim için çalıştı tek cevaptır.
cdauth

3

Jims'in çözümüne dayanarak: SQLite3'ü MySQL'e taşımanın hızlı ve kolay yolu?

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  

Bu benim için çalışıyor. Mysql benzeri olmayan ilk satırı atmak için sed kullanıyorum, ancak bu satırı atmak için dump.py komut dosyasını da değiştirebilirsiniz.


1
İçe aktarılan verilerle bazı UTF-8 kodlama sorunları vardı, ancak içe aktarma komutuna --default-character-set = utf8 ekleyerek bunu düzeltmiş gibi görünüyor. Bu soru
cevaptan alınmıştır

Tamam, bunu ekledim - tamam mı?
alekwisnia

Ekstra anahtarı burada kullanıyorum, evet.
Snips

3

SQL dökümü alın

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

Dökümü MySQL'e aktar

Küçük ithalatlar için:

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

veya

mysql -u root -p somedb < myTemporarySQLFile.sql

Bu sizden bir şifre isteyecektir. Lütfen dikkat: Şifrenizi doğrudan girmek istiyorsanız, boşluk bırakmadan, hemen sonra yapmanız gerekir -p:

mysql -u root -pYOURPASS somedb < myTemporarySQLFile.sql

Daha büyük dökümler için:

mysqlimport veya BigDump gibi diğer ithalat araçları .

BigDump size bir ilerleme çubuğu verir:

resim açıklamasını buraya girin


12
Bu küçük sözdizimi farklılıkları ve sqlite vs mysql bayrakları nedeniyle işe yaramaz. Yine de manuel olarak dönüştürmeniz gerekiyor.
dlite922

1

Ha ... keşke bunu ilk bulsaydım! Benim cevap bu yazı oldu ... mysql dökümü sql dosyasını sqlite3 db içine alınabilecek formata dönüştürmek için komut dosyası

İkisini birleştirmek tam olarak ihtiyacım olan şeydi:


Sqlite3 veritabanı ruby ​​ile kullanılacaksa değiştirmek isteyebilirsiniz:

tinyint([0-9]*) 

için:

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

ne yazık ki, bu sadece yarısı çalışır çünkü boolean işaretli bir alana 1'ler ve 0'lar ekleseniz bile, sqlite3 bunları 1'ler ve 0'lar olarak saklar, böylece geçip şöyle bir şey yapmanız gerekir:

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)

ancak tüm boolean'ları bulmak için bakılacak sql dosyasına sahip olmak yardımcı oldu.


1

Bu basit betiği Python3'e yazdım. Terminal kabuğu aracılığıyla çağrılan bir sınıf veya bağımsız komut dosyası olarak kullanılabilir. Varsayılan olarak tüm tamsayıları int(11)ve dizeleri olarak içe aktarır varchar(300), ancak bunların tümü sırasıyla yapıcı veya komut dosyası bağımsız değişkenlerinde ayarlanabilir.

NOT: MySQL Bağlayıcısı / Python 2.0.4 veya üstünü gerektirir

Aşağıdaki kodu okumak zor geliyorsa GitHub'daki kaynağa bir bağlantı: 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

Bu senaryo, bu dava dışında tabii ki tanıştım, tamam:

"Requestcomparison_stopword" DEĞERLERİNE EKLE (149, 'f');
"Requestcomparison_stopword" VALUES (420, 't');

Komut dosyası bu çıktıyı vermelidir:

İstek karşılaştırması_stopword VALUES (149, 'f');
İstek karşılaştırması_stopword VALUES (420, 't');

Ancak bunun yerine bu çıktıyı verir:

INSART INTO istek karşılaştırması_stopword VALUES (1490;
INSART INTO istek karşılaştırması_stopword VALUES (4201;

son 0 ve 1 civarında garip ascii olmayan karakterler var.

Kodun aşağıdaki satırlarına (43-46) yorum yaptığımda bu artık görünmedi, ancak diğer sorunlar ortaya çıktı:


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

Bu sadece özel bir durum, 'f' veya 't' olarak bir değer eklemek istediğimizde, ancak düzenli ifadelerle gerçekten rahat olmadığım zaman, sadece bu davanın birisi tarafından düzeltilmesini sağlamak istedim.

Neyse bu kullanışlı komut dosyası için çok teşekkürler !!!


0

Bu basit çözüm benim için çalıştı:

<?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

CREATE ifadelerine dikkat edin

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.