MySQLからのテーブルとデータを含むエクスポートSQLファイルがあり、それをSqlite 3DBにインポートしたいと思います。
それを行うための最良の方法は何ですか?
Sqlite3ツールを介してファイルをインポートするだけでは機能しません。
このシェルスクリプトはあなたを助けます
#!/bin/sh
if [ "x$1" == "x" ]; then
echo "Usage: $0 <dumpname>"
exit
fi
cat $1 |
grep -v ' KEY "' |
grep -v ' UNIQUE KEY "' |
grep -v ' PRIMARY KEY ' |
sed '/^SET/d' |
sed 's/ unsigned / /g' |
sed 's/ auto_increment/ primary key autoincrement/g' |
sed 's/ smallint([0-9]*) / integer /g' |
sed 's/ tinyint([0-9]*) / integer /g' |
sed 's/ int([0-9]*) / integer /g' |
sed 's/ character set [^ ]* / /g' |
sed 's/ enum([^)]*) / varchar(255) /g' |
sed 's/ on update [^,]*//g' |
Perl -e 'local $/;$_=<>;s/,\n\)/\n\)/gs;print "begin;\n";print;print "commit;\n"' |
Perl -pe '
if (/^(INSERT.+?)\(/) {
$a=$1;
s/\\'\''/'\'\''/g;
s/\\n/\n/g;
s/\),\(/\);\n$a\(/g;
}
' > $1.sql
cat $1.sql | sqlite3 $1.db > $1.err
ERRORS=`cat $1.err | wc -l`
if [ $ERRORS == 0 ]; then
echo "Conversion completed without error. Output file: $1.db"
rm $1.sql
rm $1.err
rm tmp
else
echo "There were errors during conversion. Please review $1.err and $1.sql for details."
fi
上記のスクリプトを機能させるために、次の変更を加えました。
私のmysqldumpコマンドは次のようになりました。
$ mysqldump -u usernmae -h Host --compatible = ansi --skip-opt -p database_name> dump_file
それからそれはうまくいきました...スクリプトに感謝します。
Sedまたはawkを使用するこれらのスクリプトのいくつかを試しましたが、おそらくMySQLデータベースのインデックスと外部キーおよび必要なmysqldumpオプションが原因で、常にエラーが発生します。
次に、Perlモジュール SQL :: Translator "ベンダー固有のSQLテーブル定義を他の形式に変換する..."を見つけました。
このモジュールは、すべての外部キーを作成し、インデックスを修正し、必要に応じて名前を変更します。
そこで、MySQLデータベースのダンプを含めてシェルスクリプトを書き直しました。スクリプト「sqlt」は構造を生成するだけであり、ダンプにデータがない場合は高速に動作するため、2つのダンプがあります。 SQL :: Translatorによってサポートされている他の変換に適合させることができることに注意してください。
このシェルスクリプトを投稿した後、質問がMySQLダンプファイルを変換しようとしていることに気付いたので、モジュールSQL :: Translatorを使用してそれを行うPerlスクリプトを実行しました。私のテストでは、オプションなしで生成されたダンプファイルを使用しました(mysqldump -u user --password database> dumpfile)。文字セットに問題はありませんでした。
他のテストでは、mysqlトリガーに問題があったため、スクリプトを変更してスキップしました。
#!/bin/sh
#===============================================================================
# USAGE: ./mysql2sqlite.sh <MySQL_database> <user>
# DESCRIPTION: Converts MySQL databases to SQLite
# Triggers are not converted
# REQUIREMENTS: mysqldump, Perl and module SQL::Translator, SQLite
#===============================================================================
if [ "$#" = 2 ]; then
USER="$2"
else
echo "Usage: $0 <MySQL_database> <user>"
exit
fi
if [ -s $1.db ]; then
read -p "File <$1.db> exists. Overwrite? [y|n] " ANS
if [ "$ANS" = "y" ] || [ "$ANS" = "Y" ] ; then
rm $1.db
else
echo "*** Aborting..."
exit
fi
fi
# extracts the necessary structure for SQLite:
mysqldump --skip-triggers --skip-add-locks --routines --no-data --compatible=ansi \
--compact -u $USER --password $1 > /tmp/$1_$$_str.sql
# verify
if [ ! -s /tmp/$1_$$_str.sql ]; then
echo "*** There are some problem with the dump. Exiting."
exit
fi
# translates MySQL syntax structure to SQLite using the script "sqlt" of the
# Perl module SQL::Translator (that corrects the foreign keys, indexes, etc.)
sqlt -f MySQL -t SQLite --show-warnings /tmp/$1_$$_str.sql \
1> /tmp/$1_$$.sqlite 2> /tmp/$1_$$_sqlt.log
# verify
if [ ! -s /tmp/$1_$$.sqlite ]; then
echo "*** There are some problem with the sql translation. Exiting."
exit
fi
# adds statements to allow to load tables with foreign keys:
echo "PRAGMA foreign_keys=OFF;" >> /tmp/$1_$$.sqlite
echo "BEGIN TRANSACTION;" >> /tmp/$1_$$.sqlite
# extracts the data (simple inserts) without locks/disable keys,
# to be read in versions of SQLite that do not support multiples inserts:
mysqldump --skip-triggers --no-create-db --no-create-info --skip-add-locks \
--skip-extended-insert --compatible=ansi --compact -u $USER \
--password $1 >> /tmp/$1_$$.sqlite
# adds statements to finish the transaction:
echo "COMMIT;" >> /tmp/$1_$$.sqlite
echo "PRAGMA foreign_keys=ON;" >> /tmp/$1_$$.sqlite
# correct single quotes in inserts
Perl -pi -e ' if (/^INSERT INTO/) { s/\\'\''/'\'\''/g; } ' /tmp/$1_$$.sqlite
# load the sql file and generate the SQLite db with the same name
# of the MySQL database
sqlite3 $1.db < /tmp/$1_$$.sqlite 2> /tmp/$1_$$sqlite.errlog
# verify
ERRORS=`cat /tmp/$1_$$sqlite.errlog | wc -l`
if [ $ERRORS = 0 ]; then
echo "* Conversion complete. Verify the file < $1.db >"
rm /tmp/$1_$$*
else
echo "*** There are some problem. Verify the files < /tmp/$1_$$* >"
fi
ここでは、SQLiteデータベースファイルのダンプファイルを変換するPerlスクリプトを示します。
#!/usr/bin/Perl
#===============================================================================
# USAGE: ./mysql2sqlite.pl <MySQL_dumpfile>
# DESCRIPTION: Converts MySQL dumpfile to SQLite database
# Triggers are not converted
# The dump must be done with
# > mysqldump --skip-triggers -u [user] --p [database] > dumpfile
# REQUIREMENTS: Perl and module SQL::Translator, SQLite
#===============================================================================
use strict;
use warnings;
use Carp;
use English qw( -no_match_vars );
use SQL::Translator;
use 5.012;
my $file = $ARGV[0];
my $filedb = $file;
$filedb =~ s/\.*[^.]*$/.db/;
if ( -s $filedb ) {
say "*** Ja existe o arquivo < $filedb >. Abandonando...";
exit;
}
my @stru;
my @data;
open( my $SQLFILE, "<", $file )
or croak "Can't open $file: $OS_ERROR";
while (<$SQLFILE>) {
# nao considera linhas com comentarios e lock/unlock/drop
next if ( /^--/ || /^\/\*/ || /^lock/i || /^unlock/i || /^drop/i );
# processa os inserts
if (/^(INSERT.+?)[(]/) {
my $ins = $1; # captura o nome da tabela
s/\\[']/''/g; # substitue aspas simples - \'
s/[)],[(]/);\n$ins(/g; # divide multiplos inserts
Push( @data, $_ );
}
# processa a estrutura
else { Push( @stru, $_ ); }
}
close($SQLFILE);
my $strusql = join( '', @stru );
my $datasql = join( '', @data );
#open( my $STRU, ">", "stru.sql" ); # to verify the results
#open( my $DATA, ">", "data.sql" );
#print $STRU $strusql;
#print $DATA $datasql;
# here the conversion
my $translator = SQL::Translator->new(
no_comments => 0,
show_warnings => 0,
quote_table_names => 1,
quote_field_names => 1,
validate => 1,
);
my $struout = $translator->translate(
from => 'MySQL',
to => 'SQLite',
data => \$strusql,
# filename => $file,
) or croak "Error: " . $translator->error;
# define inicio e final da transacao de inserts
my $prgini = "PRAGMA foreign_keys=OFF;\n";
my $traini = "BEGIN TRANSACTION;\n";
my $trafin = "COMMIT;\n";
my $prgfin = "PRAGMA foreign_keys=ON;\n";
#gera o arquivo final sqlite
my $sqlout = join( "\n", $struout, $prgini, $traini, $datasql, $trafin, $prgfin);
open( my $FINAL, ">", "/tmp/final.sql" );
print $FINAL $sqlout;
# Monta o SQLite database
my $log = "/tmp/sqlite.errlog";
my $command = "sqlite3 $filedb < /tmp/final.sql 2> $log";
system($command) == 0 or die "system $command failed: $?";
if ( -s $log ) {
say "*** Houve algum problema. Verifique o arquivo < /tmp/sqlite.errlog > ";
}
else {
say "*** Conversao completa. Verifique o arquivo < $filedb > ";
}
MysqlデータベースがISO-8859-1(Latin-1)であるという問題がありました。 sqlite3への変換は、データがUTF-8であると想定したときに、デコードエラーが発生しました。
これで修正するのは簡単でした:
iconv -f ISO-8859-1 -t UTF-8 mysql_dump_file> mysql_dump_file_utf8
これが誰かを助ける場合に備えて。
BLOBを含むデータベースを変換するために、mysqldumpコマンドに--hex-blobを追加し、パイプライン化されたsedのリストに以下を追加しました。-
sed -e "s/,0x\([0-9A-Z]*\),/,X'\L\1',/g" |
これは、mysqlの16進ダンプ文字列を置き換えます。 0x010A…。 sqliteでインポートするためのX’010a… ’を使用します。
少なくとも、mysql 5.0.xでは、sqlite3にインポートする前に、mysqlのダンプからcollate utf8_unicode_ciを削除する必要がありました。そこで、sedsのリストに以下を含めるようにスクリプトを変更しました。
_sed 's/ collate utf8_unicode_ci/ /g' |
_
更新:
MySQLはブールフィールドを「tinyint(1)」として扱うため、次を追加する必要がありましたbeforetinyint([0-9]*)
sed:
sed 's/ tinyint(1) / boolean /g' |
また、mysql db(本番)をRuby on Railsアプリケーションのsqlite3db(開発)に複製しようとしているので、自動インクリメントの主キーを設定するには、次の行を追加します。
_sed 's/) NOT NULL/) PRIMARY KEY AUTOINCREMENT NOT NULL/g' |
_
[〜#〜] key [〜#〜]エントリをmysqlから対応するCREATE INDEX sqlite3のエントリに変更する方法をまだ見つけようとしています。
Sqlite3データベースをRubyで使用する場合は、以下を変更することをお勧めします。
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ファイルを調べることは役に立ちました。
これは、ssqlを.dbに変換するための、最もよく記述され、十分に文書化されたシェルスクリプトです。
https://Gist.github.com/esperlu/943776
またはこのツールを使用する方が良いです驚くほど高速ESFデータベース移行ツールキット。
ここですべてのスクリプトを試した後、esfツールを使用するまで機能しませんでした。
注意 :
Trial version add a 'T' to the begingn of each text value you have But the pro version worked like a charm :)
centos 5.364ビットで正常に動作します。出力ファイルをロードしたら、次のようにします。
Shell> sqlite3 file_name.dbSQLiteバージョン3.3.6手順については「.help」と入力してくださいsqlite> .databases seq name file
0メイン/current_directory/file_name.db
sqlite> select * from table; 。 。 。 。 。結果... sqlite> .quit