문제

누구나 알고 빠르고 쉬운 방법은 마이그레이션 SQLite3 데이터베이스를 MySQL?

도움이 되었습니까?

해결책

여기에는 목록의 변환기(지 않 업데이트 이후 2011 년):


대체 방법으로 일하는 것이 좋지만은 거의 언급은:사용 ORM 클래스는 초록은 특정 데이터베이스의 차이점을 멀리한다.예:당신이 얻을 이 PHP(RedBean),Python(장고의 ORM 층 폭풍, 정밀한 웹 애플리케이션을 빨리 빌),Ruby on Rails(ActiveRecord),코코아(CoreData)

즉당신이 이렇게 할 수 있다:

  1. 드에서 데이터 원본을 사용하여 데이터베이스 ORM 클래스입니다.
  2. 데이터를 메모리에 저장하거나 직렬화하여 디스크에 있습니다.
  3. 데이터 저장으로 목적지를 사용하여 데이터베이스 ORM 클래스입니다.

다른 팁

모두 보을 시작으로 몇 greps 및 perl 표현하고 당신은 그렇 좀 얻을 작동하는 무언가를 위한 특정 데이터 집합을 하지만 당신은 아무 생각이 없다면 그것의 수입된 데이터를 올바르게 또는하지 않습니다.내가 심각하게는 놀라게 아무도 내장 솔리드 라이브러리에 변환할 수 있습니다.

여기에 모든 목록 차이점에서 SQL 구문을 내가 알고 있는 사이에 대한 두 개의 파일 형식은:라인으로 시작:

  • 트랜잭션을 시작
  • COMMIT
  • sqlite_sequence
  • CREATE UNIQUE INDEX

에서 사용되지 않 MySQL

  • SQLlite 사용 CREATE TABLE/INSERT INTO "table_name" 고 MySQL 사용 CREATE TABLE/INSERT INTO table_name
  • MySQL 사용하지 않는 따옴표 안의 스키마 정의
  • MySQL 사용하는 작은 따옴표 문자열에 대한 내부 INSERT INTO
  • SQLlite 및 MySQL 있는 다른 방법으로 탈출의 내부 문자열 INSERT INTO
  • SQLlite 사용 't''f' 부울에 대한,MySQL 사용 10 (는 간단하 regex 이 실패할 수 있습니다면 당신이 문자열을 다음과 같:'나는,당신은\'t'당신 INSERT INTO)
  • SQLLite 사용 AUTOINCREMENT, MySQL 사용 AUTO_INCREMENT

여기에 매우 기본적인 해킹 perl 스크립트는 작동 데이터 세트와 검사를 위해 더 많은 이러한 조건의 다른 perl 스크립트가 웹에서 찾을 수 있습니다.뉴 guarentees 는 작업에 대한 데이터를 수정을 게시합니다.

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

여기에는 python 스크립트,내장의 Shalmanese 의 대답하고 어떤 도움 알렉스 마르텔에서 이상 번역 Perl Python

나는 그것을 만드는 커뮤니티에 위키므로,주시기 바랍 편집,과 리팩터로 그것이 중단되지 않는 기능을(다행히도 우리는 그냥 돌아)-그것은 매우 못생긴 하지만 작동

사용처럼 너무(가정의 스크립트가 불리 dump_for_mysql.py:

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

할 수 있습니다 다음으로 가져올 수 mysql

참고-당신이 추가할 필요가 외국 키를 제한하기 때문에 수동으로 sqlite 지 않는 실제로 그들을 지원

여기에는 이 스크립트:

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

그것은 지저분하기 때문에 파일을 덤프하는 데이터베이스는 공급업체 특정합니다.

사용하는 경우에 레일이,훌륭한 플러그인이 존재합니다.읽기: http://blog.heroku.com/archives/2007/11/23/yamldb_for_databaseindependent_data_dumps/

업데이트

현재로 유지 포크: https://github.com/ludicast/yaml_db

MySQL 작업(GPL 라이센스)에서 마이그레이션 SQLite 게 데이터베이스를 마이그레이션 마법사.설치 Windows,Ubuntu,RHEL 페 OS X.

놀라게 아무도 이것을 언급에 의해 지금,하지만 실제로 거기 도구에 대해 명시적으로 이것이다.그것은에서는 perl,SQL:역:http://sqlfairy.sourceforge.net/

변환 사이에 대부분의 어떠한 형태의 테이블 형식의 데이터(SQL 다른 형식,Excel 스프레드시트),그리고 심지어 다이어그램의 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

나는 그냥 갔을 통해 이 프로세스,그리고 많은 매우 좋은 도움과 정보를 이 Q/A 지만,내가 찾을 함께 다양한 요소(플러스 일부를 다른 Q/As)을 얻을 작동하는 솔루션을 성공적으로 마이그레이션합니다.

그러나 그 후에도,결합하는 기존의 답변을,내가 찾는 Python 스크립트는 완전히 돌아오지 못했는 작업에 대한 전체적으로 깔끔하고 세련된 느낌이 작동하지 않았습니 거기 여러 boolean 발생에 삽입합니다.보 왜는 경우입니다.

그래서 저는 생각이 나는 게시물 내 병합니다.신용 간 사람들에 기여한 다른 곳에서 물론이다.하지만 내가 원하는 무언가를 돌려주고,다른 사람을 저장 시간을 따릅니다.

난 후 아래 스크립트.하지만 첫째,여기에 대한 지침 변환...

나는 스크립트를 실행 OS X10.7.5 사자입니다.Python 했습니다.

를 생성하 MySQL 입력 파일로서 귀하의 기존 SQLite3 데이터베이스,스크립트를 실행에 당신의 자신의 파일에 다음과 같다,

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

그때 나는 복사한 결과 dumped_sql.sql 파일을 통해 우분투 리눅스 10.04.4LTS 내 MySQL 데이터베이스가 살고 있습니다.

다른 내용을 가져올 때 MySQL 파일이었는 유니코드 UTF-8 개 문자를(특히 작은 따옴표)하지 않을 때 제대로 가져온다,그래서 나를 추가하는 스위치를 명령어를 지정하 UTF-8 입니다.

그 결과 명령을 입력으로 데이터를 때리는 새로운 빈 MySQL 데이터베이스는 다음과 같습니다:

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

그것이 요리해야 하는것!것을 잊지 마세히 조사하기 위해 데이터를 전후입니다.

그래서,로 요청한,빠르고 쉽게 때,당신은 방법을 알고있다!:-)

으로,따로 한 가지는 확실하지 않았기 전에 대해 보았으로 이러한 마이그레이션,었는지 여부를 created_at 및 updated_at 필드 값을 보존할 것-에 대한 좋은 소식이 나가는 그들은,그래서 나는 마이그레이션할 수 내 기존의 생산이다.

행운을 빕니다!

업데이트

을 만들고 있기 때문에 이 스위치를 나타났는 문제가 이전에 발견되지 않았다.내 레일 응용 프로그램,내 텍스트 필드에 정의된'문자열의',그리고 이를 통해 수행하는 데이터베이스에 스키마.프로세스는 여기에 설명된 결과 이러한되고 있으로 정의 VARCHAR(255)에서 MySQL 데이터베이스입니다.이 장소를 255 문자로 제한에 이러한 분야기-고 그 이상 아무것도 이 자동으로 잘리는 중에 가져오.을 지원하는 텍스트 보다 큰 길이를 255,MySQL 스키마을 사용할 필요가 텍스트 보다는 오히려 VARCHAR(255),내가 믿습니다.정의된 프로세스는 여기에 포함하지 않는 이러한 변환.


여기에는 병합되고 개정 Python 스크립트는 일에 대한 데이터:

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

아마 다른 쉬운 방법이 사용하여 sqlite.덤프 명령,이 경우에는 덤프를 만들어 샘플의 데이터베이스입니다.

sqlite3 sample.db .dump > dump.sql

할 수 있습(이론)가져오는 이로 mysql 데이터베이스에서,이 경우 테스트 데이터베이스에 데이터베이스 서버 127.0.0.1 를 사용하여,사용자가 root.

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

나는 말에서 이론으로 약간의 차이가 있는 사 grammars.

에 sqlite 트랜잭션 시작

BEGIN TRANSACTION;
...
COMMIT;

MySQL 사용

BEGIN;
...
COMMIT;

있는 기타 유사한 문제를 해결하기 위해(varchars 과 쌍따옴표 봄에 다시 마음)하지만 아무것도를 찾아 교체할 수 없다.

아마도 당신이해야 이유를 물어 당신은 당신의 마이그레이션 경우,성능/데이터베이스 크기는 문제입니다 아마도 살펴 reoginising 경우,스키마 이 시스템은로 이동하는 더 강력한 제품이 될 수 있는 이상적인 시간의 미래를 계획합니다.

사용하는 경우에는 파이썬/장고 그것은 매우 쉽습니다:

두 개를 만들에서 데이터베이스 settings.py (여기에서 좋아하는 https://docs.djangoproject.com/en/1.11/topics/db/multi-db/)

그런 다음 다만 다음과 같다:

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

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

나는 최근에게 마이그레이션에서 MySQL 을 JavaDB 프로젝트에 대해는 우리 팀에서 작동.내가 발견 자바 라이브러리에 의해 작성된 아파치라고 DdlUtils 는 것이 매우 쉽습니다.그는 API 를 제공합을 통해 다음을 수행할 수 있습니다:

  1. Discover 데이터베이스의 스키마와 그것으로 수출 XML 파일입니다.
  2. 수정 DB 를 기반으로 이 schema.
  3. 레코드 가져오기 하나에서 DB,다른 가정은 그들이 동일한 스키마가 있습니다.

도구는 우리는 끝나지 않은 완전히 자동화되어,그러나 그들은 정상적으로 작동합니다.응용 프로그램을 개발하는 경우에도지에서 Java,그것은 너무 어려운 채찍질하는 몇 가지 작은 도구들도 한 번 마이그레이션입니다.나는 생각할 수 있었을 당겨 우리의 마이그레이션과 150 미만 라인의 코드입니다.

을 얻을 SQL 덤프

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

가져오기 덤프하 MySQL

을 위해 작은 수입품:

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

mysql -u root -p somedb < myTemporarySQLFile.sql

이 묻는 메시지를 표시합니다 암호를 입력합니다.참고:하려면 비밀번호를 입력 직접,당신은 그것을 할 수 없는 공간,후 직접 -p:

mysql -u root -pYOURPASS somedb < myTemporarySQLFile.sql

량 덤:

mysqlimport 또는 다른 가져오기 도구 BigDump.

BigDump 게 진행됩:

enter image description here

Python 스크립트 후 일을 몇 가지 수정을 다음과 같다:

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

...

할 필요가 없이 어떤 스크립트,명령,etc....

당신이 단지 내보내기 sqlite 데이터베이스로 데이터베이스 .csv 파일이 가져와서 Mysql 를 사용하여 phpmyadmin.

나는 그것을 사용하고 놀라운...

내가 사용하는 로더 데이터 마이그레이션을 위한 거의 모든 데이터를 변환하 MSSQL MYSQL,MS 액세스를 MSSQL,mysql,csv 로더,foxpro 및 MSSQL MS 액세스,MYSQl,CSV,foxpro etc.에서 보이는 최고의 데이터 마이그레이션 도구

무료로 다운로드: http://www.dbload.com

에 따라 Jims 의 솔루션:빠르고 쉬운 방법은 마이그레이션 SQLite3MySQL?

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  

이 나를 위해 작동 합니다.내가 사용하는 sed 을 던져 먼저 선하지 않은,mysql-지만,당신이뿐만 아니라 수정 dump.py 스크립트를 던져 이 선습니다.

Ha...나는 이 처음!내 응답을 이 게시물을... 스크립트로 변환하 mysql 덤프 sql 파일로 가져올 수 있는 형식으로 되어 있습으로 sqlite3db

결합하는 것 두 가지 정확히 무엇을 내가 필요하다:


때 sqlite3 데이터베이스에 사용되는 것 루비 변경 할 수 있습니다:

tinyint([0-9]*) 

하기:

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

슬프게도,이 절반만 작동에도 불구하고 있기 때문에 당신은 삽입하는 1 과 0 으로 표시된 필드 boolean,sqlite3 저장하는 1 과 0 그래서 당신이 통과해야 하고 다음과 같습니다.

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)

하지만 그것은 도움이 되었습니 sql 파일에서 볼을 찾아 모든 부울.

fallino 올바르게 식별하의 위치에 오류가 스크립트입니다.저는 솔루션입니다.문제는 다음과 같은 라인:

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

대체 패턴(2 번째 매개 변수)이다.하위를 호출은"일반"문자열이다,그래서 대신의\1 로 확대 첫 번째 정규 표현식과 일치,확장 리터럴 0x01.마찬가지로,\2 확장을 0x02.예를 들어,포함하는 라인:'t','f' 것으로 대체:<0x01>10<0x02>
(최초 대체 변경,'t',하기 <0x1>1<0x2> 두 번째로 대체 변경 <0x02>'f',하기 <0x1>0<0x1>)

정을 변경하거나 교체 문자열을 추가하여'r'접두사에 의해 또는 탈출\1\2 에서 기존의 문자열입니다.이후로 쉽게 조작의 정규 표현식 문자열은 무엇을 원료 문자열은,여기에 수용:

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

이 소프트웨어의자이자 나를 위해 작동 합니다.그것을 시도하고자 다른 알고있다.

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

또한 다음 사항에 주의합니다.

나는 하나의 작은 변경:어떻게든 다음의 특징의 하나는 분야(는 분야에서 발견된 오류 메시지)를 사용할 수 없습니다.그래서 phpmyadmin 을 확인 속성 A_I 이 필드의하고 그것을 완전히 작동합니다.도움이 되기를 바랍니다.

Dunn.

이 간단한 스크립트에서 Python3.사용될 수 있습으로 포함되어 있는 클래스나 독립형 스크립트를 통해 호출되는 터미널 쉘입니다.기본적으로 수입하는 모든 정수로 int(11)과 문자열로 varchar(300), 지만,모든 것을 조정할 수 있습에서 생성자 또는 스크립트의 인수를 각각합니다.

참고: 그것은 필요 MySQL 커넥터/Python2.0.4 또는 높

여기에 대한 링크를 소스에 GitHub 경우 아래 코드를 읽기 어렵게: 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()

나는 일반적으로 사용 내보내기/가져오기 테이블 기능 IntelliJ DataGrip.

step 1 step 2 step 3

당신이 볼 수 있는 진도에서 오른쪽 하단 모서리.

[enter image description here]

이 스크립트입니다 확인을 제외한 이 경우는 물론,I've met:

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

스크립트를 제공해야이 출력:

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

그 대신 출력:

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

어떤 이상한 비-ascii 문자를 주변에 마지막 0 과 1.

이 표시되지 않은 더 이상 때 나는 댓글을 다음과 같은 라인의 코드(43-46)하지만 다른 문제가 나타났:


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

이것은 단지는 특별한 경우,우리가 원하는 값을 추가되는'f'또는''t 하지만 난 정말 편안한 정규 표현식,I just wanted to 소 이 경우 수정하여 사람입니다.

어쨌든 덕분에 많은 대한 스크립트입니다!!!

이 간단한 해결책이 나를 위해 일했:

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

가 Python 스크립트 https://stackoverflow.com/a/32243979/746459 (위)및 수요에 대처하는 우리 자신의 sqlite 스키마.거기에 몇 가지 문제를 처리합니다.

당신은 그것을 찾을 수 있습니다 소스에서 여기 제어: https://bitbucket.org/mjogltd/sqlite3mysql

또한 사용 가능한 같은 일을 감싸으로커 이미지,여기: https://hub.docker.com/r/mjog/sqlite3mysql/ -그것은 완전히 사용할 수 있도에서 Windows 바탕 화면이 나타납니다.

내가 주의깊게 확인 모두에 대한 답변이 포스트뿐만 아니라,대답을 다른 관련 게시물 번역 Perl Python.아직 아무도 수 있는 완전히 내 문제를 해결한다.

나의 시나리오는 내가 필요한 마이그레이션하는 데이터베이스의 Trac 에서 sqlite MySQL,그리고 데이터베이스는 많은 기술 기반이 위키의 내용.따라서 내부 INSERT INTO 값이 있을 수 있습 SQL 다음과 같은 문장 CREATE TABLEAUTOINCREMENT.하지만 줄 교체할 수 있는 잘못된 교체가 있다.

결국은 내가 쓴 나의 자신의 도구는 이러한 목적으:

https://github.com/motherapp/sqlite_sql_parser

사용이 상대적으로 간단하다:

python parse_sqlite_sql.py export.sql

두 개의 파일을 생성되: export.sql.schema.sqlexport.sql.data.sql.하나를 위한 업데이트 DB 스키마와는 다른 대한 업데이트 DB 데이터입니다.

하나 할 수 있는 추가 설명서에 수정 DB 스키마 파일을 사용하여 어떤 텍스트 편집기에 대한 걱정 없이 변경 내용입니다.

그것을 희망할 수 있는 데 도움이 다른 사람에 미래입니다.

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

계를 위한 문을 만들 수

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top