Швидкий простий спосіб перенести SQLite3 до MySQL? [зачинено]


224

Хтось знає швидкий простий спосіб перенести базу даних SQLite3 до MySQL?

Відповіді:


62

Ось список перетворювачів (не оновлюється з 2011 року):


Альтернативний метод, який би добре працював, але його рідко згадують: використовувати клас ORM, який дозволяє уникати певних відмінностей баз даних. наприклад, ви отримуєте їх у PHP ( RedBean ), Python (шар ORM Django, Storm , SqlAlchemy ), Ruby on Rails ( ActiveRecord ), какао ( CoreData )

тобто ви могли це зробити:

  1. Завантажте дані з вихідної бази даних за допомогою класу ORM.
  2. Зберігати дані в пам'яті або серіалізувати на диск.
  3. Зберігання даних у базі даних призначення за допомогою класу ORM.

107

Здається, кожен починається з декількох виразів із виразами та перламутром, і ви, начебто, отримуєте щось, що працює для вашого конкретного набору даних, але ви не знаєте, чи правильно імпортуються дані чи ні. Я серйозно здивований, що ніхто не створив міцну бібліотеку, яка може конвертувати між ними.

Ось список ВСІХ відмінностей у синтаксисі SQL, про які я знаю, між двома форматами файлів: Рядки, що починаються з:

  • ПОЧАТОЧНА ПЕРЕХОДА
  • КОМІТЕТ
  • sqlite_sequence
  • СТВОРТИ УНІКАЛЬНИЙ ІНДЕКС

не використовуються в MySQL

  • Використовує SQLlite CREATE TABLE/INSERT INTO "table_name"та MySQLCREATE TABLE/INSERT INTO table_name
  • MySQL не використовує лапок всередині визначення схеми
  • MySQL використовує одинарні лапки для рядків всередині INSERT INTOпропозицій
  • У SQLlite та MySQL є різні способи виходу рядків всередину INSERT INTOпропозицій
  • SQLlite використовує 't'і 'f'для booleans, MySQL використовує 1і 0(простий регулярний вираз для цього може вийти з ладу, якщо у вас є рядок типу: "Я роблю, ви не \ 'т' всередині себе INSERT INTO)
  • Використовує SQLLite, використовує AUTOINCREMENTMySQLAUTO_INCREMENT

Ось дуже простий скрипт perl, який працює для мого набору даних і перевіряє чи багато інших цих умов, що інші сценарії Perl, які я знайшов в Інтернеті. Не гарантуйте, що він працюватиме для ваших даних, але не соромтесь змінювати та розміщувати тут.

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

8
Алекс Мартеллі виконав велику роботу , переписуючи це як пітон більш в stackoverflow.com/questions/1067060/perl-to-python
Jiaaro

Я додав повний скрипт python (сам сценарій perl не дуже працював для мене ... потрібна була додаткова обробка для обробки іноземних ключів та індексів)
Jiaaro

Я переписав цю відповідь на інше питання stackoverflow.com/questions/1067060/_/1070463#1070463
Бред Гілберт,

2
COMMIT і СТВОРИТИ УНІКАЛЬНИЙ ІНДЕКС - дійсні команди MySQL, виправте їх.
niutech

5
Я розумію, що ваш сценарій "швидкий і брудний", але також дуже корисний, тому ось кілька доповнень / виправлень: * після && ($line !~ /CREATE UNIQUE INDEX/)додавання && ($line !~ /PRAGMA foreign_keys=OFF/) * регулярний вирівнювання таблиці імен пропускає цифри, тобто замість $line =~ /INSERT INTO \"([a-z_]*)\"(.*)/цього повинно бути $line =~ /INSERT INTO \"([a-z_1-9]*)\"(.*)/ сподівання, що це допомагає майбутньому читачі
Michał Leon

50

Ось сценарій пітона, побудований за допомогою відповіді Шалманеза та деякої допомоги від Алекса Мартеллі в перекладі 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,

2
Привіт Джиме, на моєму наборі даних кожен перший оператор INSERT загортається зворотним котируванням замість однієї цитати: __ DROP TABLE IF EXISTS schema_migrations; СТВОРИТИ ТАБЛИЦУ, ЯКЩО НЕ МОЄТЬСЯ schema_migrations( versionvarchar (255) NOT NULL); ВСТАВИТИ схему_міграції VALUES ( 20100714032840); ВСТАВИТИ схему_міграції VALUES ('20100714033251'); __
Девід

ну ... це не відображається вище, але зворотні котирування з’являються всередині ЦІННОСТІ ([ТУТ] 20100714032840 [/ ТУТ])
Девід

1
AUTOINCREMENT у Mysql - AUTO_INCREMENT. Сценарій цього не враховує.
giuseppe

Це не працює для бази даних вікі-медіа. Багато помилок: Blobvarтип даних, зворотні тики в CREATE-виписці ...
Франк Хайнш

1
не працює. Можливо, не всі умови враховані ...
Хіманшу Бансал

10

Напевно, найпростішим способом є використання команди sqlite .dump, у цьому випадку створити дамп зразкової бази даних.

sqlite3 sample.db .dump > dump.sql

Потім ви можете (теоретично) імпортувати це в базу даних mysql, в цьому випадку тестову базу даних на сервері баз даних 127.0.0.1, використовуючи root користувача.

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

Я кажу в теорії, оскільки між граматиками є кілька відмінностей.

У sqlite починаються транзакції

BEGIN TRANSACTION;
...
COMMIT;

MySQL використовує просто

BEGIN;
...
COMMIT;

Є й інші подібні проблеми (вархари та подвійні цитати повертаються до уваги), але нічого знайти та замінити неможливо виправити.

Можливо, вам слід запитати, чому ви мігруєте, якщо проблема / розмір бази даних є проблемою, можливо, подивіться на повторне використання схеми, якщо система переходить до більш потужного продукту, це може бути ідеальним часом для планування майбутнього ваших даних.


2
але найбільш важким завданням є різниця 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

7

Я щойно пройшов цей процес, і в цьому питанні є дуже багато хорошої допомоги та інформації, але я виявив, що мені довелося зібрати різні елементи (плюс деякі з інших запитань), щоб отримати робоче рішення в щоб успішно мігрувати.

Однак, навіть поєднавши наявні відповіді, я виявив, що скрипт Python для мене не працює повністю, оскільки він не працює там, де в INSERT було кілька булевих випадків. Дивіться тут чому так було.

Отже, я подумав, що викладу тут свою об'єднану відповідь. Звичайно, кредити належать тим, хто зробив внесок у інше місце. Але я хотів щось повернути і заощадити інший час, що слідує за цим.

Я опублікую сценарій нижче. Але по-перше, ось інструкція щодо конверсії ...

Я запустив сценарій на OS X 10.7.5 Lion. Пітон працював із коробки.

Щоб генерувати вхідний файл MySQL з вашої існуючої бази даних SQLite3, запустіть сценарій для власних файлів наступним чином,

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

Потім я скопіював отриманий файл dumped_sql.sql у вікно Linux, на якому працює Ubuntu 10.04.4 LTS, де повинна перебувати моя база даних MySQL.

Інша проблема, яка виникала при імпорті файлу MySQL, полягала в тому, що деякі символи UTF-8 Unicode (зокрема окремі лапки) були імпортовані неправильно, тому мені довелося додати команду до команди, щоб вказати UTF-8.

Отримана команда для введення даних у шипучу нову порожню базу даних MySQL наступна:

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

Нехай вариться, і це повинно бути! Не забувайте ретельно перевіряти свої дані до і після.

Тож, як цього вимагав ОП, це швидко і просто, коли ви знаєте, як! :-)

З іншого боку, я не був впевнений, до того, як я переглянув цю міграцію, - чи будуть збережені значення___ та оновлені_а_ поля поля - хороша новина для мене полягає в тому, що вони є, тому я міг перенести свої наявні виробничі дані.

Удачі!

ОНОВЛЕННЯ

З моменту переключення я помітив проблему, яку раніше не помічав. У моїй програмі Rails мої текстові поля визначені як "рядок", і це переходить до схеми бази даних. Описаний тут процес призводить до того, що вони визначаються як VARCHAR (255) у базі даних MySQL. Це ставить обмеження в 255 символів для цих розмірів поля - і все, що перевищує це, мовчки скорочено під час імпорту. Для підтримки довжини тексту більше 255, я вважаю, що для схеми MySQL потрібно використовувати "TEXT", а не 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,

1
Дякую. Сценарій, як написано в даний час, має в ньому синтаксичну помилку; рядок "else:" у рядку 41 знаходиться не на належному рівні відступу. Мені незрозуміло, чи слід відступати рядки над ним з відступом чи відбувається щось інше. Хочете оновити?
Дан Тененбаум


5

Нещодавно мені довелося перейти з MySQL на JavaDB для проекту, над яким працює наша команда. Я знайшов бібліотеку Java, написану Apache під назвою DdlUtils, що зробило це досить просто. Він надає API, який дозволяє робити наступні дії:

  1. Відкрийте схему бази даних та експортуйте її у XML-файл.
  2. Змініть БД на основі цієї схеми.
  3. Імпортуйте записи з однієї БД в іншу, припускаючи, що вони мають однакову схему.

Інструменти, які ми закінчили, не були повністю автоматизовані, але вони працювали досить добре. Навіть якщо ваша програма не знаходиться на Java, вам не повинно бути занадто складно згорнути кілька невеликих інструментів для одноразової міграції. Я думаю, що мені вдалося витягнути нашу міграцію з менш ніж 150 рядків коду.


4

Немає необхідності в будь-якому скрипті, команді тощо ...

вам потрібно експортувати лише свою базу даних sqlite у вигляді .csvфайлу, а потім імпортувати її в Mysql за допомогою phpmyadmin.

Я використав це, і це спрацювало дивовижно ...


У поєднанні з цим , це єдина відповідь, яка працювала на мене.
cdauth

3

На основі рішення 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, щоб відкинути цей рядок.


1
У мене виникли деякі проблеми кодування UTF-8 із імпортованими даними, але додавання --default-character-set = utf8 до команди import імпортує це. Взяте з цього питання: stackoverflow.com/questions/346092/…
Snips

Гаразд, я додав це - це нормально?
alekwisnia

Ось де я використовую додатковий перемикач, так.
Сніпи

3

Отримайте дамп 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 дає панель прогресу:

введіть тут опис зображення


12
Це не працює через незначні синтаксичні відмінності та прапори в sqlite vs mysql. Ще потрібно вручну перетворити його.
dlite922

1

Ха ... Я б хотів, щоб я знайшов це першим! Моя відповідь була на цю посаду ... скрипт для перетворення файлу дамп sql у формат, який можна імпортувати в sqlite3 db

Поєднання двох було б саме те, що мені потрібно:


Коли база даних sqlite3 буде використовуватися з рубіном, ви можете змінити:

tinyint([0-9]*) 

до:

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

на жаль, ця лише половина працює, тому що, хоча ви вставляєте значки 1-х та 0-х у поле, позначене булевими, 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, щоб знайти всі булеви.


1

Я написав цей простий сценарій в Python3. Він може використовуватися як включений клас або окремий сценарій, викликаний через оболонку терміналу. За замовчуванням він імпортує всі цілі числа як int(11)і рядки як varchar(300), але все, що може бути відрегульовано відповідно в аргументах конструктора або сценарію.

ПРИМІТКА. Для цього потрібен MySQL Connector / Python 2.0.4 або вище

Ось посилання на джерело на GitHub, якщо ви знайдете код, який важко читати нижче: 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

Цей сценарій добре, за винятком цього випадку, що, звичайно, я зустрів:

ВСТАВЛЯЙТЬСЯ в "запит порівняння_сторінка" ВАЛЮТНІСТЬ (149, 'f');
ВСТАВЛЯЙТЬСЯ у "запит порівняння_сторінка" ВІДНІШНІСТЬ (420, 't');

Сценарій повинен дати такий вихід:

ВСТАВИТИ ЗАПРОБУВАННЯ запиту_сторінка VALUEES (149, 'f');
ВСТАВИТИ ЗАПРОБУВАННЯ запиту_сторінка VALUEES (420, 't');

Але дає замість цього вихід:

ВСТАВЛЯЙТЕ ЗАПРОШУВАННЯ запитів_сторінкові значення: 1490;
ВСТАВЛЯЙТЕ ЗАПИТВАННЯ запиту_сторінка ЗНАЧЕННЯ (4201;

з деякими дивними персонажами, які не входять в асоціювання, навколо останніх 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", але мені не дуже зручно з регулярними виразами, я просто хотів помітити, що цей випадок хтось виправить.

У будь-якому випадку, велике спасибі за цей зручний сценарій !!!


0

Це просте рішення працювало для мене:

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.