Как зайти в Даркнет?!
25th January, 01:11
8
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
900
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
952
0
Очень долго работает Update запрос Oracle
27th January, 09:58
916
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
907
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
942
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1727
0
период по дням
25th October, 10:44
3957
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3722
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4614
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4382
0
Помогите пожалуйста решить задачи
24th November, 23:53
6088
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4352
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4400
0
Метода Крамера С++
23rd October, 11:55
4309
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2599
0
Быстрый простой способ перенести SQLite3 в MySQL?
Кто-нибудь знает быстрый и простой способ переноса базы данных SQLite3 в MySQL?
Каждый, кажется, начинает с нескольких greps и выражений perl, и вы вроде как получаете что-то, что работает для вашего конкретного набора данных, но вы понятия не имеете, правильно ли он импортировал данные или нет. Я серьезно удивлен, что никто не построил надежную библиотеку, которая может конвертировать между ними.
Вот список из ALL различий в синтаксисе SQL, которые я знаю о двух форматах файлов: Строки, начинающиеся с:
- НАЧАТЬ ТРАНЗАКЦИЮ
- COMMIT
- sqlite_sequence
- СОЗДАТЬ УНИКАЛЬНЫЙ ИНДЕКС
не используются в 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 использует1и0(простой regex для этого может не сработать, если у вас есть строка типа: 'I do, you don\'t' inside yourINSERT INTO) - SQLLite использует
AUTOINCREMENT, MySQL используетAUTO_INCREMENT
Вот очень простой взломанный скрипт perl, который работает для моего набора данных и проверяет многие другие из этих условий, которые я нашел в интернете. Nu гарантирует, что он будет работать для ваших данных, но не стесняйтесь изменять и публиковать их здесь.
#! /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;
}
}
Вот список конвертеров (не обновлялся с 2011 года):
Альтернативный метод, который будет работать хорошо, но редко упоминается, это: используйте класс ORM, который абстрагирует определенные различия в базе данных для вас. например, вы получаете их в PHP (RedBean ), Python (Django-й слой ORM , шторм, SqlAlchemy), Ruby на Rails ( ActiveRecord ), Cocoa ( CoreData )
то есть вы могли бы сделать это:
- Загрузите данные из исходной базы данных с помощью класса ORM.
- Храните данные в памяти или сериализуйте на диск.
- Храните данные в целевой базе данных, используя класс ORM.
Вот сценарий python, построенный на основе ответа Шалманезе и некоторой помощи Алекса Мартелли в переводе Perl на Python
Я делаю это сообщество wiki, поэтому, пожалуйста, не стесняйтесь редактировать и рефакторировать, пока это не нарушает функциональность (к счастью, мы можем просто откатить назад) - это довольно уродливо, но работает
используйте like so (предполагая, что скрипт называется 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,
Это грязно, потому что файлы дампа зависят от поставщика базы данных.
Если вы используете Rails, для этого существует отличный плагин. Читать: http://blog.heroku.com/archives/2007/11/23/yamldb_for_databaseindependent_data_dumps/
Обновление
В настоящее время поддерживается fork: https://github.com/ludicast/yaml_db
MySQL Workbench (лицензия GPL) очень легко переносится с SQLite с помощью мастера переноса базы данных . Устанавливается на Windows, Ubuntu, RHEL, Fedora и OS X.
Удивительно, что никто до сих пор не упомянул об этом, но на самом деле есть инструмент, явно предназначенный для этого. Это в perl, SQL:Translator году: 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
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 не полностью работает для меня, так как он не работал там, где было несколько булевых вхождений в INSERT. Смотрите здесь , почему это было так.
Поэтому я решил разместить свой объединенный ответ здесь. Разумеется, заслуга принадлежит тем, кто внес свой вклад в других странах. Но я хотел дать что-то взамен и сэкономить другим время, которое последует за этим.
Я опубликую сценарий ниже. Но во-первых, вот инструкции для преобразования...
Я запустил скрипт на OS X 10.7.5 Lion. Python работал из коробки.
Чтобы создать входной файл 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, заключалась в том, что некоторые символы unicode UTF-8 (особенно одинарные кавычки) импортировались неправильно, поэтому мне пришлось добавить переключатель в команду, чтобы указать UTF-8.
Результирующая команда для ввода данных в новую пустую базу данных spanking MySQL выглядит следующим образом:
Snips$ mysql -p -u root -h 127.0.0.1 test_import --default-character-set=utf8 < dumped_data.sql
Пусть варится, и все тут! Не забудьте тщательно изучить ваши данные, до и после.
Итак, как и просил OP, это быстро и легко, когда вы знаете, как это сделать! :-)
Кроме того, одна вещь, в которой я не был уверен до того, как я изучил эту миграцию, заключалась в том, будут ли сохранены значения полей created_at и updated_at - хорошая новость для меня заключается в том, что они есть, поэтому я мог бы перенести свои существующие производственные данные.
Удачи вам!
UPDATE
С тех пор как я сделал этот переход, я заметил проблему, которую раньше не замечал. В моем приложении Rails мои текстовые поля определяются как 'string', и это переносится в схему базы данных. Описанный здесь процесс приводит к тому, что они определяются как 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,
Вероятно, самый быстрый и простой способ-это использование команды sqlite .dump, в этом случае создайте дамп образца базы данных.
sqlite3 sample.db .dump > dump.sql
Затем вы можете (теоретически) импортировать это в базу данных mysql, в данном случае тестовую базу данных на сервере базы данных 127.0.0.1, используя корень пользователя.
mysql -p -u root -h 127.0.0.1 test < dump.sql
Я говорю в теории, так как есть несколько различий между грамматиками.
В sqlite транзакции начинаются
BEGIN TRANSACTION;
...
COMMIT;
MySQL использует только
BEGIN;
...
COMMIT;
Есть и другие подобные проблемы (варчары и двойные кавычки spring обратно на ум), но ничего найти и заменить не удалось исправить.
Возможно, вам следует спросить, почему вы переходите, если размер базы данных performance/ является проблемой, возможно, посмотрите на реогинизацию схемы, если система переходит на более мощный продукт, это может быть идеальным временем для планирования будущего ваших данных.
Если вы используете 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')
Недавно мне пришлось перейти с MySQL на JavaDB для проекта, над которым работает наша команда. Я нашел библиотеку Java, написанную Apache под названием DdlUtils , которая сделала это довольно легко. Он предоставляет API, что позволяет сделать следующее:
- Откройте схему базы данных и экспортируйте ее в виде файла XML.
- Измените DB на основе этой схемы.
- Импортируйте записи из одной 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;
moose@pc08$ sqlite3 mySqliteDatabase.db .dump > myTemporarySQLFile.sql
moose@pc08$ mysql -u <username> -p
Enter password:
....
mysql> use somedb;
Database changed
mysql> source myTemporarySQLFile.sql;
или
mysql -u root -p somedb < myTemporarySQLFile.sql
После этого вам будет предложено ввести пароль. Пожалуйста, обратите внимание: если вы хотите ввести свой пароль непосредственно, вы должны сделать это WITHOUT пробел, непосредственно после -p :
mysql -u root -pYOURPASS somedb < myTemporarySQLFile.sql
Для больших отвалов:
mysqlimport или другие инструменты импорта, такие как BigDump .
BigDump дает вам индикатор выполнения:
Скрипт 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('"', "'")
...
На основе решения Джимса: Быстрый простой способ перенести 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, чтобы выбросить эту строку.
Я использую загрузчик данных для переноса практически любых данных, это помогает мне конвертировать MSSQL в MYSQL, MS к MSSQL, mysql, csv погрузчик, foxpro и MSSQL в MS доступ, MYSQl, CSV, foxpro и т. д. На мой взгляд это лучший инструмент миграции данных
Скачать Бесплатно : http://www.dbload.com
фаллино правильно определил местоположение ошибки в скрипте. У меня есть решение. Проблема заключается в следующих строках:
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-й параметр) в вызовах re.sub представляет собой строку "regular", поэтому вместо \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')
Ха... Жаль, что я не нашел его первым! Мой ответ был на этот пост... скрипт для преобразования файла mysql dump sql в формат, который можно импортировать в базу данных sqlite3
Сочетание этих двух вещей было бы именно тем, что мне нужно:
Когда база данных sqlite3 будет использоваться с ruby, вы можете изменить ее:
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, чтобы посмотреть на него, чтобы найти все логические значения.