script pour convertir mysql dump fichier sql dans le format qui peut être importé dans sqlite3 db

j'ai un fichier SQL d'exportation contenant des tables et des données de MySQL et je veux l'importer dans un Sqlite 3 DB.

Quelle est la meilleure façon de le faire?

importer simplement le fichier via l'outil sqlite3 ne fonctionne pas.

20
demandé sur graup 2009-01-28 23:48:12

9 réponses

ce script shell vous aide

#!/bin/sh
if [ "x" == "x" ]; then
   echo "Usage: "151900920" <dumpname>"
   exit
fi
cat  |
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=;
     s/\'\''/'\'\''/g;
     s/\n/\n/g;
     s/\),\(/\);\n$a\(/g;
  }
  ' > .sql
cat .sql | sqlite3 .db > .err
ERRORS=`cat .err | wc -l`
if [ $ERRORS == 0 ]; then
  echo "Conversion completed without error. Output file: .db"
  rm .sql
  rm .err
    rm tmp
else
   echo "There were errors during conversion.  Please review .err and .sql for details."
fi
23
répondu Igor 2009-01-28 20:57:01

pour que le script ci-dessus fonctionne, j'ai fait les changements suivants:"

  1. exécuter avec #!/ bin /bash
  2. ajouter deux seds à la liste des seds pipelinés:
    • sed 's/\\r\\n/\\n/g'
    • sed 's / \\" / "/ g'
  3. la ligne 'rm tmp' est une No-op (à moins que vous ayez un fichier nommé 'tmp' qui traîne :O)
  4. ma commande mysqldump ressemble à ceci:

    $ mysqldump -u usernmae-h host --compatible=ansi --skip-opt -P database_name > dump_file

alors ça a bien marché... merci pour le script.

7
répondu Mike Fogel 2009-06-24 23:14:43

j'ai essayé certains de ces scripts qui utilisent sed ou awk, mais il se produit toujours une erreur, probablement en raison des index et des clés étrangères de ma base de données MySQL et des options mysqldump nécessaires.

puis j'ai trouvé le module Perl SQL::Translator "qui convertit les définitions de table SQL spécifiques au vendeur dans d'autres formats..."

Ce module crée toutes les clés étrangères et corrige les index, en changeant les noms si nécessaire.

donc, j'ai réécrit le script shell, y compris le dump De La base de données MySQL. Il y a deux dumps car le script "sqlt" ne génère la structure et ne fonctionne rapidement que si le dump n'a pas de données. Notez qu'il peut être adapté à d'autres conversions supportées par le traducteur SQL::.

après avoir posté ce script shell, j'ai réalisé que la question était sur le point de convertir un fichier dump MySQL, donc j'ai fait un script Perl qui fait ça, en utilisant le module SQL::Translator. Dans mes tests, j'ai utilisé un fichier dump généré sans options ( mysqldump-u user --password database > dumpfile ). Je n'avais pas de problèmes avec les jeux de caractères.

dans un autre test, j'ai eu des problèmes avec les déclencheurs mysql, donc j'ai modifié les scripts pour les sauter.

#!/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=""    
else
    echo "Usage: "151900920" <MySQL_database> <user>"
    exit
fi
if [ -s .db ]; then
    read -p "File <.db> exists. Overwrite? [y|n] " ANS
    if [ "$ANS" = "y" ] || [ "$ANS" = "Y" ] ; then
        rm .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  > /tmp/_$$_str.sql
# verify
if [ ! -s /tmp/_$$_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/_$$_str.sql \
    1> /tmp/_$$.sqlite 2> /tmp/_$$_sqlt.log
# verify
if [ ! -s /tmp/_$$.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/_$$.sqlite
echo "BEGIN TRANSACTION;" >> /tmp/_$$.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  >> /tmp/_$$.sqlite
# adds statements to finish the transaction:
echo "COMMIT;" >> /tmp/_$$.sqlite
echo "PRAGMA foreign_keys=ON;" >> /tmp/_$$.sqlite
# correct single quotes in inserts
perl -pi -e ' if (/^INSERT INTO/) { s/\'\''/'\'\''/g; } ' /tmp/_$$.sqlite
# load the sql file and generate the SQLite db with the same name 
# of the MySQL database
sqlite3 .db < /tmp/_$$.sqlite 2> /tmp/_$$sqlite.errlog
# verify
ERRORS=`cat /tmp/_$$sqlite.errlog | wc -l`
if [ $ERRORS = 0 ]; then
    echo "* Conversion complete. Verify the file < .db >"
    rm /tmp/_$$*
else
    echo "*** There are some problem. Verify the files < /tmp/_$$* >"
fi

voici le script Perl pour convertir un fichier dumpfile dans un fichier de base de données SQLite.

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

5
répondu nfuria 2012-03-30 20:40:27

j'ai eu un problème avec le fait que la base de données mysql soit ISO-8859-1 (Latin-1). Quand est-ce que la conversion en sqlite3 a supposé que les données étaient UTF-8 résultant en erreurs de décodage.

il était facile de fixer avec ceci:

iconv-F ISO-8859-1 -T UTF-8 mysql_dump_file > mysql_dump_file_utf8

au cas où cela aiderait quelqu'un.

2
répondu amjoconn 2010-10-28 16:31:03

lorsque la base de données sqlite3 sera utilisée avec ruby, vous pouvez changer:

tinyint([0-9]*) 

à:

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

hélas, cela ne fonctionne qu'à moitié parce que même si vous insérez des 1 et des 0 dans un champ booléen marqué, sqlite3 les stocke comme des 1 et des 0 de sorte que vous devez passer et faire quelque chose comme:

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)

mais il était utile d'avoir le fichier sql à regarder pour trouver toutes les opérations booléennes.

1
répondu daicoden 2010-03-30 06:38:12

au moins, avec mysql 5.0.x, j'ai dû supprimer collate utf8_unicode_ci du dump de mysql avant de l'importer dans sqlite3. J'ai donc modifié le script pour inclure ce qui suit à la liste des seds:

sed 's/ collate utf8_unicode_ci/ /g' |

mise à jour:

MySQL traite les champs booléens comme " tinyint (1)", donc j'ai dû ajouter le suivant avant tinyint([0-9]*) sed:

sed 's/ tinyint(1) / boolean /g' |

aussi, puisque j'essaie de répliquer un db mysql (production) à un db sqlite3 (développement) d'une application Ruby on Rails, j'ai dû ajouter la ligne suivante afin de définir une clé primaire auto-incrémentée:

sed 's/) NOT NULL/) PRIMARY KEY AUTOINCREMENT NOT NULL/g' |

je suis toujours en train d'essayer de trouver un moyen de changer la clé entrées de mysql à son correspondant créer L'INDEX entrée de sqlite3.

1
répondu Srinidhi 2011-07-17 21:01:08

pour convertir les bases de données avec des BLOBs dedans j'ai ajouté --hex-blob à la commande mysqldump et le suivant à la liste de seds pipelined: -

sed -e "s/,0x\([0-9A-Z]*\),/,X'\L',/g" |

remplace les chaînes de dump HEX mysql par exemple 0x010A.... avec X'010A... ' pour importer avec sqlite.

1
répondu goelectric 2013-02-13 17:36:38

C'est le meilleur script shell écrit et bien documenté pour convertir ssql en .db

https://gist.github.com/esperlu/943776

ou une meilleure utilisation de cet outils, C'est incroyable et rapide ESF Database Migration Toolkit .

après avoir essayé tout le script ici, il n'a pas fonctionné jusqu'à ce que j'ai utilisé l'outil esf .

Note :

Trial version add a 'T' to the begingn of each text value you have 
 But the pro version worked like a charm :)
1
répondu ucefkh 2013-11-24 04:52:37

fonctionne très bien sur Centos 5.3 64bit. une fois que vous avez le fichier de sortie le charger comme ceci:

shell> sqlite3 file_name.DB Version 3.3.6 de SQLite Entrer." aide" pour les instructions sqlite> .les bases de données seq nom de fichier


0 principal /current_directory/nom_fichier.db

sqlite > select * de la table; . . . . . résultat... sqlite>.quitter

0
répondu themattreid 2010-01-09 00:06:09