13.05.2008 1:30: MySQL nach SQLite exportieren
Zum Exportieren von MySQL-Datenbanken nach SQLite gibt es bei http://www.sqlite.org/ ein kleines Shellscript, das aber bei mir leider nicht so ganz zufriedenstellend funktionieren wollte. Vor allem nicht mit diesem Beitrag hier ;) Darum habe ich mir erlaubt, das Script ein wenig zu modifizieren:
#!/bin/sh
if [ "x$1" == "x" ]; then
echo "Usage: $0 <dbname>"
exit
fi
if [ -e "$1.db" ]; then
echo "$1.db already exists. I will overwrite it in 15 seconds if you do not press CTRL-C."
COUNT=15
while [ $COUNT -gt 0 ]; do
echo "$COUNT"
sleep 1
COUNT=$((COUNT - 1))
done
rm $1.db
fi
mysqldump -u root -p --compact --compatible=ansi --default-character-set=binary $1 |
grep -v '^\( KEY "\)' |
grep -v '^\( UNIQUE KEY "\)' |
grep -v '^\( PRIMARY KEY \)' |
grep -v '^\(SET \)' |
sed 's/ / /g' |
sed 's/ primary key autoincrement/ primary key autoincrement/gi' |
sed 's/ smallint([0-9]*) / integer /gi' |
sed 's/ tinyint([0-9]*) / integer /gi' |
sed 's/ int([0-9]*) / integer /gi' |
sed 's/ ]* / /gi' |
sed 's/ enum([^)]*) / varchar(255) /gi' |
sed 's/,]*//gi' |
sed 's/\\//g' |
sed 's/\\"/"/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
else
echo "There were errors during conversion. Please review $1.err and $1.sql for details." fi
Leider werden mit dieser Version alle Zeilenumbrüche, die innerhalb eines INSERT INTO <table> in der Form \n erscheinen, durch tatsächliche Zeilenumbrüche ersetzt. In Codebeispielen innerhalb von Artikeln können aber auch \n vorkommen, siehe oben. Solche Codebeispiele werden dann zu wirrem Wirrwarr. Also muß noch eine weitere Verbessserung eingebaut werden.
Allerdings ist es etwas kniffelig, mit Regexen die zu ersetzenden \n von denen, die in Codebeispielen drinbleiben sollen, zu unterscheiden. Ich habe zwar ein paar Sachen mit Backreferences ausprobiert, aber aus Zeitmangel gab ich mich vorerst damit zufrieden, in obigem Script die Zeile
s/\\n/\n/g;durchs/(?<!(\s<code>))(\\n)(?!(\\\)|(\"))|(\/)|(\$)|(\)))/\n/g;zu ersetzen. Das ist vielleicht nicht besonders elegant und deckt natürlich lange nicht alle denkbaren Fälle ab, in denen \n in Codebeispiel-Zeilen erscheinen kann. Wenn meine Muße es zuläßt, werde ich demnächst eine bessere Lösung suchen, hoffentlich finden und hier veröffentlichen.