This is a perl script I’ve used to move data from mysql 5.1 to postgres 9, this script doesn’t create a schema, it only grabs the data from mysql and try to put it on the same table in postgres.
The only requirement is DBI for mysql and postgres.
#!/usr/bin/perl # # this script moves all the data from mysql to postgres # modules required are: # # http://search.cpan.org/~timb/DBI-1.616/DBI.pm # # please change the dsn, srcUser/srcPass and dstUser/Pass variables. use DBI; use strict; my $srcUser = 'ivan'; my $srcPass = '123'; my $srcDbName = 'datatocopy'; my $srcDbHost = 'mini'; my $dstUser = 'ivan'; my $dstPass = '456'; my $dstDbName = 'migrateddata'; my $dstDbHost = '192.168.1.145'; ### do not modify ## my $srcDb = DBI->connect("dbi:mysql:database=$srcDbName;host=$srcDbHost", $srcUser, $srcPass) or die; my $dstDb = DBI->connect("dbi:Pg:database=$dstDbName;host=$dstDbHost", $dstUser, $dstPass) or die; ####main######## print "Starting to move data from $srcDbHost to $dstDbHost\n"; $srcDb->do("SET NAMES \'UTF8\'"); $dstDb->do("SET CLIENT_ENCODING=\'UTF8\'") or die; my $srcTables = $srcDb->selectall_arrayref("SHOW TABLES"); my $dstTables = $dstDb->selectall_hashref("SELECT * FROM pg_tables WHERE NOT tablename ~\'^(pg_|sql_)\'","tablename"); my $seqlist = $dstDb->selectall_arrayref("SELECT RELNAME FROM pg_class WHERE relkind=\'S\'"); my $seqmap; foreach my $s(@$seqlist) { my $seqname = $s->[0]; if ($seqname=~/^(.*)_([a-z]+)_([a-z]+$)/) { my $item; $item->{seq}=$seqname; $item->{field}=$2; my $table = $1; if (exists $dstTables->{$table}) { push @{$seqmap->{$table}},$item; } else { print STDERR "WARN: cannot find table for sequence $seqname\n"; } } } $dstDb->{AutoCommit}=0; my $totalRowCount = 0; foreach my $t(@$srcTables) { my $table = $t->[0]; unless (exists $dstTables->{$table}) { print STDERR "WARN: table $table does not exists in dest db Pg:$dstDbName\n"; next; } print "Clearing data from table $table in $dstDbHost\n"; clear_table($dstDb,$table); next if $table=~/^cache/; next if $table=~/^locales/; print "Copying data from mysql table $table in $srcDbHost to postgres table $table in $dstDbHost\n"; my $cnt = copy_table($srcDb,$dstDb,$table) unless $table=~/^cache/; $totalRowCount = $totalRowCount + $cnt; print "$cnt rows copied ($table)\n"; init_seq($dstDb,$table,$seqmap->{$table}); # if (exists $seqmap->{$table}); } print "Commiting changes \n"; $dstDb->commit; print "$totalRowCount rows were copied.\n"; exit 0; sub init_seq { my ($db,$table,$list)=@_; return unless $list; for my $item (@{$list}) { my $ref = $db->selectall_arrayref("SELECT MAX($item->{field}) FROM $table") or die; my $val = $ref->[0]->[0]; if ($val) { $db->do("SELECT SETVAL(\'$item->{seq}\',$val)") or die; } } } sub clear_table { my ($dbh,$table)=@_; return unless $table; $dbh->do("DELETE FROM $table") or die; } sub copy_table { my ($srcDb,$dstDb,$table)=@_; die unless $table; my $slf = $srcDb->prepare("select * from $table limit 1"); my $rows = $slf->execute() or die; return 0 if $rows < 1; my $rec1 = $slf->fetchrow_hashref; $slf->finish; my @fieldnames = sort keys %$rec1; my @qm = map { '?'} @fieldnames; my $ins = $dstDb->prepare("INSERT INTO $table (".join(",",@fieldnames).") VALUES(".join(",",@qm).")"); my $sel = $srcDb->prepare("SELECT * FROM $table"); $sel->execute or die; my $cnt = 0; while (my $data = $sel->fetchrow_hashref) { $ins->execute(map {$data->{$_}} @fieldnames) or die; $cnt++; } $ins->finish; $sel->finish; return $cnt; }


