有人知道一个快速简单的方法来迁移SQLite3数据库到MySQL吗?


当前回答

下面是一个python脚本,基于Shalmanese的回答和Alex martelli在翻译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,

其他回答

如果你使用的是Python/Django,这很简单:

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

基于Jims的解决方案: 快速简单的方法迁移SQLite3到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  

这对我很有用。我只使用sed来丢弃第一行,这与mysql不一样,但是您也可以修改dump.py脚本来丢弃这一行。

以下是转换器列表(自2011年以来没有更新):

https://www2.sqlite.org/cvstrac/wiki?p=ConverterTools(或在archive.org上快照)

另一种工作得很好但很少被提及的方法是:使用一个ORM类,为您抽象出特定的数据库差异。例如,你在PHP (RedBean), Python (Django的ORM层,Storm, SqlAlchemy), Ruby on Rails (ActiveRecord), Cocoa (CoreData)中得到这些

例如,你可以这样做:

使用ORM类从源数据库加载数据。 将数据存储在内存中或序列化到磁盘。 使用ORM类将数据存储到目标数据库中。

这个简单的解决方案对我很有效:

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

获取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;

or

mysql -u root -p somedb < myTemporarySQLFile.sql

这将提示您输入密码。请注意:如果你想直接输入你的密码,你必须不带空格,直接在-p后输入:

mysql -u root -pYOURPASS somedb < myTemporarySQLFile.sql

对于较大的转储:

mysqlimport或其他导入工具,如BigDump。

BigDump给你一个进度条: