Bất cứ ai cũng biết một cách dễ dàng nhanh chóng để di chuyển cơ sở dữ liệu SQLite3 sang MySQL?
Bất cứ ai cũng biết một cách dễ dàng nhanh chóng để di chuyển cơ sở dữ liệu SQLite3 sang MySQL?
Câu trả lời:
Dưới đây là danh sách các bộ chuyển đổi (không được cập nhật từ năm 2011):
tức là bạn có thể làm điều này:
Mọi người dường như bắt đầu với một vài biểu thức greps và perl và bạn sắp xếp một cái gì đó phù hợp với tập dữ liệu cụ thể của bạn nhưng bạn không biết liệu nó có nhập dữ liệu chính xác hay không. Tôi thực sự ngạc nhiên khi không ai xây dựng một thư viện vững chắc có thể chuyển đổi giữa hai.
Dưới đây là danh sách TẤT CẢ sự khác biệt trong cú pháp SQL mà tôi biết về giữa hai định dạng tệp: Các dòng bắt đầu bằng:
không được sử dụng trong MySQL
CREATE TABLE/INSERT INTO "table_name"
và sử dụng MySQLCREATE TABLE/INSERT INTO table_name
INSERT INTO
mệnh đềINSERT INTO
các mệnh đề't'
và 'f'
cho booleans, MySQL sử dụng 1
và 0
(một regex đơn giản cho việc này có thể thất bại khi bạn có một chuỗi như: 'Tôi làm, bạn không \' t 'bên trong của bạn INSERT INTO
)AUTOINCREMENT
, sử dụng MySQLAUTO_INCREMENT
Dưới đây là một tập lệnh perl đã bị hack rất cơ bản, hoạt động cho tập dữ liệu của tôi và kiểm tra nhiều điều kiện khác mà các tập lệnh perl khác tôi tìm thấy trên web. Nu guarentees rằng nó sẽ hoạt động cho dữ liệu của bạn nhưng hãy thoải mái sửa đổi và đăng lại ở đây.
#! /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;
}
}
&& ($line !~ /CREATE UNIQUE INDEX/)
thêm && ($line !~ /PRAGMA foreign_keys=OFF/)
* biểu thức khớp với tên bảng bỏ lỡ các chữ số, điều đó thay vì $line =~ /INSERT INTO \"([a-z_]*)\"(.*)/
phải có $line =~ /INSERT INTO \"([a-z_1-9]*)\"(.*)/
Hy vọng điều này sẽ giúp tương lai độc giả
Đây là một kịch bản python, được xây dựng từ câu trả lời của Shalmanese và một số trợ giúp từ Alex martelli tại Dịch thuật Perl sang Python
Tôi đang biến nó thành wiki cộng đồng, vì vậy xin vui lòng chỉnh sửa và tái cấu trúc miễn là nó không phá vỡ chức năng (rất may chúng tôi chỉ có thể quay lại) - Nó khá xấu nhưng hoạt động tốt
sử dụng như vậy (giả sử tập lệnh được gọi là dump_for_mysql.py
:
sqlite3 sample.db .dump | python dump_for_mysql.py > dump.sql
Mà sau đó bạn có thể nhập vào mysql
lưu ý - bạn cần thêm các ràng buộc khóa ngoại theo cách thủ công vì sqlite không thực sự hỗ trợ chúng
đây là kịch bản:
#!/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,
schema_migrations
( version
varchar (255) KHÔNG NULL); XÁC NHẬN VÀO lược đồ_migations VALUES ( 20100714032840
); XÁC NHẬN VÀO lược đồ_migations GIÁ TRỊ ('20100714033251'); __
Blobvar
kiểu dữ liệu, dấu tích ngược trong câu lệnh CREATE ...
Có lẽ cách nhanh nhất dễ nhất là sử dụng lệnh sqlite .dump, trong trường hợp này tạo ra một bãi chứa cơ sở dữ liệu mẫu.
sqlite3 sample.db .dump > dump.sql
Sau đó, bạn có thể (về lý thuyết) nhập dữ liệu này vào cơ sở dữ liệu mysql, trong trường hợp này là cơ sở dữ liệu thử nghiệm trên máy chủ cơ sở dữ liệu 127.0.0.1, sử dụng root người dùng.
mysql -p -u root -h 127.0.0.1 test < dump.sql
Tôi nói trong lý thuyết vì có một vài khác biệt giữa các ngữ pháp.
Trong giao dịch sqlite bắt đầu
BEGIN TRANSACTION;
...
COMMIT;
MySQL chỉ sử dụng
BEGIN;
...
COMMIT;
Có những vấn đề tương tự khác (varchars và double trích dẫn trở lại trong tâm trí) nhưng không có gì tìm và thay thế không thể khắc phục.
Có lẽ bạn nên hỏi tại sao bạn di chuyển, nếu kích thước hiệu suất / cơ sở dữ liệu là vấn đề có thể nhìn vào việc tái hiện lại lược đồ, nếu hệ thống chuyển sang một sản phẩm mạnh hơn thì đây có thể là thời điểm lý tưởng để lập kế hoạch cho tương lai của dữ liệu của bạn.
Nếu bạn đang sử dụng Python / Django, điều đó khá dễ dàng:
tạo hai cơ sở dữ liệu trong settings.txt (như ở đây https://docs.djangoproject.com/en/1.11/topics/db/multi-db/ )
sau đó chỉ cần làm như thế này:
objlist = ModelObject.objects.using('sqlite').all()
for obj in objlist:
obj.save(using='mysql')
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
Tôi thường sử dụng tính năng xuất / nhập bảng của IntelliJ DataGrip .
Bạn có thể thấy sự tiến bộ ở góc dưới bên phải.
[ ]
Tôi vừa trải qua quá trình này, và có rất nhiều trợ giúp và thông tin rất tốt trong Q / A này, nhưng tôi thấy tôi phải tập hợp nhiều yếu tố khác nhau (cộng với một số từ Q / As khác) để có được giải pháp hoạt động để di chuyển thành công.
Tuy nhiên, ngay cả sau khi kết hợp các câu trả lời hiện có, tôi thấy rằng tập lệnh Python không hoạt động hoàn toàn đối với tôi vì nó không hoạt động khi có nhiều lần xuất hiện boolean trong một INSERT. Xem ở đây tại sao đó là trường hợp.
Vì vậy, tôi nghĩ rằng tôi sẽ đăng câu trả lời hợp nhất của mình ở đây. Tín dụng cho những người đã đóng góp ở nơi khác, tất nhiên. Nhưng tôi muốn trả lại một cái gì đó và tiết kiệm thời gian cho những người khác.
Tôi sẽ đăng kịch bản dưới đây. Nhưng trước tiên, đây là hướng dẫn chuyển đổi ...
Tôi đã chạy tập lệnh trên OS X 10.7.5 Lion. Python làm việc ra khỏi hộp.
Để tạo tệp đầu vào MySQL từ cơ sở dữ liệu SQLite3 hiện tại của bạn, hãy chạy tập lệnh trên các tệp của riêng bạn như sau,
Snips$ sqlite3 original_database.sqlite3 .dump | python ~/scripts/dump_for_mysql.py > dumped_data.sql
Sau đó, tôi đã sao chép tệp dumped_sql.sql sang hộp Linux chạy Ubuntu 10.04.4 LTS nơi cơ sở dữ liệu MySQL của tôi cư trú.
Một vấn đề khác tôi gặp phải khi nhập tệp MySQL là một số ký tự unicode UTF-8 (cụ thể là dấu ngoặc đơn) không được nhập chính xác, vì vậy tôi phải thêm một công tắc vào lệnh để chỉ định UTF-8.
Lệnh kết quả để nhập dữ liệu vào cơ sở dữ liệu MySQL trống rỗng mới như sau:
Snips$ mysql -p -u root -h 127.0.0.1 test_import --default-character-set=utf8 < dumped_data.sql
Hãy để nó nấu ăn, và đó nên là nó! Đừng quên xem xét kỹ lưỡng dữ liệu của bạn, trước và sau.
Vì vậy, như OP yêu cầu, thật nhanh chóng và dễ dàng, khi bạn biết cách! :-)
Bên cạnh đó, một điều tôi không chắc chắn trước khi tôi xem xét việc di chuyển này, là liệu các giá trị trường created_at và update_at có được giữ nguyên hay không - tin tốt cho tôi là chúng, vì vậy tôi có thể di chuyển dữ liệu sản xuất hiện có của mình.
Chúc may mắn!
CẬP NHẬT
Kể từ khi thực hiện chuyển đổi này, tôi đã nhận thấy một vấn đề mà trước đây tôi chưa nhận thấy. Trong ứng dụng Rails của tôi, các trường văn bản của tôi được định nghĩa là 'chuỗi' và điều này mang đến lược đồ cơ sở dữ liệu. Quá trình được phác thảo ở đây dẫn đến kết quả được xác định là VARCHAR (255) trong cơ sở dữ liệu MySQL. Điều này đặt giới hạn 255 ký tự cho các kích thước trường này - và bất cứ điều gì ngoài phạm vi này đều bị cắt ngắn trong quá trình nhập. Để hỗ trợ độ dài văn bản lớn hơn 255, lược đồ MySQL sẽ cần sử dụng 'TEXT' thay vì VARCHAR (255), tôi tin. Quá trình được xác định ở đây không bao gồm chuyển đổi này.
Đây là tập lệnh Python được hợp nhất và sửa đổi, hoạt động cho dữ liệu của tô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,
Gần đây tôi đã phải di chuyển từ MySQL sang JavaDB cho một dự án mà nhóm chúng tôi đang thực hiện. Tôi đã tìm thấy một thư viện Java được viết bởi Apache có tên là DdlUtils , điều này làm cho việc này khá dễ dàng. Nó cung cấp một API cho phép bạn làm như sau:
Các công cụ mà chúng tôi đã kết thúc với không hoàn toàn tự động, nhưng chúng hoạt động khá tốt. Ngay cả khi ứng dụng của bạn không có trong Java, thì cũng không quá khó khăn để sử dụng một vài công cụ nhỏ để thực hiện di chuyển một lần. Tôi nghĩ rằng tôi đã có thể thực hiện việc di chuyển của chúng tôi với ít hơn 150 dòng mã.
Không cần bất kỳ kịch bản, lệnh, v.v ...
bạn chỉ phải xuất cơ sở dữ liệu sqlite của mình dưới dạng .csv
tệp và sau đó nhập nó vào Mysql bằng phpmyadmin.
Tôi đã sử dụng nó và nó hoạt động tuyệt vời ...
Dựa trên giải pháp của Jims: Cách nhanh chóng dễ dàng để di chuyển SQLite3 sang 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
Điều này làm việc cho tôi. Tôi sử dụng sed chỉ để ném dòng đầu tiên, không giống như mysql, nhưng bạn cũng có thể sửa đổi tập lệnh dump.txt để ném dòng này đi.
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;
hoặc là
mysql -u root -p somedb < myTemporarySQLFile.sql
Điều này sẽ nhắc bạn nhập mật khẩu. Xin lưu ý: Nếu bạn muốn nhập mật khẩu trực tiếp, bạn phải thực hiện mà KHÔNG cần dung lượng, ngay sau -p
:
mysql -u root -pYOURPASS somedb < myTemporarySQLFile.sql
mysqlimport hoặc các công cụ nhập khẩu khác như BigDump .
BigDump cung cấp cho bạn một thanh tiến trình:
Ha ... tôi ước tôi đã tìm thấy cái này đầu tiên! Phản hồi của tôi là bài viết này ... script để chuyển đổi tập tin mysql dump sql thành định dạng có thể được nhập vào sqlite3 db
Kết hợp cả hai sẽ chính xác những gì tôi cần:
Khi cơ sở dữ liệu sqlite3 sẽ được sử dụng với ruby, bạn có thể muốn thay đổi:
tinyint([0-9]*)
đến:
sed 's/ tinyint(1*) / boolean/g ' |
sed 's/ tinyint([0|2-9]*) / integer /g' |
than ôi, điều này chỉ hoạt động được một nửa vì mặc dù bạn đang chèn 1 và 0 vào một trường được đánh dấu boolean, sqlite3 lưu trữ chúng là 1 và 0 nên bạn phải trải qua và làm một cái gì đó như:
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)
nhưng thật hữu ích khi có tệp sql để xem để tìm tất cả các booleans.
Tôi đã viết kịch bản đơn giản này trong Python3. Nó có thể được sử dụng như một lớp bao gồm hoặc tập lệnh độc lập được gọi thông qua trình bao đầu cuối. Theo mặc định, nó nhập tất cả các số nguyên dưới dạng int(11)
và chuỗi nhưvarchar(300)
, nhưng tất cả những gì có thể được điều chỉnh trong các đối số của hàm tạo hoặc tập lệnh tương ứng.
GHI CHÚ: Nó yêu cầu Trình kết nối MySQL / Python 2.0.4 trở lên
Đây là một liên kết đến nguồn trên GitHub nếu bạn thấy mã dưới đây khó đọc: 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()
Kịch bản này ổn, ngoại trừ trường hợp này, tất nhiên, tôi đã gặp:
XÁC NHẬN VÀO "requestcomparison_stopword" GIÁ TRỊ (149, 'f'); XÁC NHẬN VÀO "requestcomparison_stopword" GIÁ TRỊ (420, 't');
Kịch bản sẽ cung cấp đầu ra này:
XÁC NHẬN VÀO requestcomparison_stopword GIÁ TRỊ (149, 'f'); XÁC NHẬN VÀO requestcomparison_stopword GIÁ TRỊ (420, 't');
Nhưng thay vào đó là đầu ra:
XÁC NHẬN VÀO requestcomparison_stopword GIÁ TRỊ (1490; XÁC NHẬN VÀO requestcomparison_stopword GIÁ TRỊ (4201;
với một số ký tự không phải ascii lạ xung quanh 0 và 1 cuối cùng.
Điều này đã không xuất hiện nữa khi tôi nhận xét các dòng mã sau (43-46) nhưng các vấn đề khác xuất hiện:
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')
Đây chỉ là một trường hợp đặc biệt, khi chúng tôi muốn thêm một giá trị là 'f' hoặc 't' nhưng tôi không thực sự thoải mái với các biểu thức thông thường, tôi chỉ muốn phát hiện trường hợp này để được ai đó sửa.
Dù sao cũng cảm ơn rất nhiều cho kịch bản tiện dụng đó !!!
Giải pháp đơn giản này đã làm việc cho tôi:
<?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 ) );
}
}