This little script will aid in your database backup. It will copy the data from one database to another, but the table definitions must be present in the empty DB. Currently only supports mysql platform. Tested -- DBI 1.14, mysql 3.23.43, Redhat 2.2.19 Enjoy!
#!/usr/local/bin/perl ####################### # dbCopy.pl # Version 1.0 # This utility can backup the data from one mysql database to another. # It requires that the table definitions on your production # database + are in place in the backup database. # TODO: # 1. Parse Table Definitions to issue create table # statements to backup db. # 2. Extend to other DB Platforms # 3. Write in Package Format, possibly as DBI::Utils or something ###################### use DBI; main(); # Initialize values for DBI connection. # $dbHref is the DB to be backed up [eg, production]. # $dbBakHref is the backup database # Change the hash values to your own needs. sub initDBHash { my ($dbHRef,$dbBakHRef) = @_; %$dbHRef = ( dbName => "dbName", dbUser => "dbUser", dbPWord => "dbPass" ); %$dbBakHRef = ( dbName => "dbBakName", dbUser => "dbBakUser", dbPWord => "dbBakPass" ); } # Create DBI object in the accepted hash ref. sub dbConnect { my $hRef = shift; $$hRef{connect}=DBI->connect ("dbi:mysql:$$hRef{dbName}", "$$hRef{dbUser}","$$hRef{dbPWord}", {AutoCommit=>1, PrintError=>0}); } sub main { my (%dbHash,%dbBakHash); initDBHash (\%dbHash,\%dbBakHash); #Connect to each DB for (\%dbHash,\%dbBakHash) { dbConnect($_); } #Get Table Names my $tableRefs = getData ("show tables",\%dbHash); #Loop through each table foreach my $table (@$tableRefs) { #Get data from current table my $rowRefs = getData ("select * from $$table[0]",\%dbHash); #Build bind string, using map to get correct number of ?'s -- ?,?, +?,?..... my $str = join (",",map {"?"}(0..$#{$rowRefs->[0]})); #Create Handle for DBBackup insert, using $str bind values. my $insert = $dbBakHash{connect}->prepare ("insert into $$tabl +e[0] values ($str)"); #Execute the insertion over each row. foreach my $row (@$rowRefs) { $insert->execute (@$row); } } #Disconnect $dbHash{connect}->disconnect(); $dbBakHash{connect}->disconnect(); } #Prepare,execute,and retrieve data from SQL statement. sub getData { my ($sql,$dbHash) = @_; my $query = $$dbHash{connect}->prepare("$sql"); $query->execute(); my $rows = $query->fetchall_arrayref(); $rows; }

Replies are listed 'Best First'.
Re: dbCopy.pl
by gav^ (Curate) on Feb 03, 2002 at 07:29 UTC
    A few short points:

  • You can create a hash ref like this:
    $hr = { x => 1, y => 2 };

  • Don't use
    $$dbHash{connect}->prepare("$sql")
    when
    $db->{connect}->prepare($sql)
    is so much cleaner

  • Using:
    $str = join(',', ('?') x @{$row->[0]}))
    seems cleaner to me than
    $str = join (",",map {"?"}(0..$#{$rowRefs->[0]})

  • I like to call my statement handles $sth so I can remember what they are ($sth_insert, $sth_delete, etc if I need multiple ones).

  • why the main()? ... this isn't C :)

  • personally I don't like your functions that make the DBI calls (dbConnect & getData), they just seem to complicate things

  • Also this doesn't add any value than using mysqldump which has a lot more useful options.

    Hope this helps...

    gav^

      The hashref is passed to a sub. {} notation isn't quite so effective.

      Using $${ref} is a matter of style. I like $$ for straight refs, -> for obj. refs

      Forgot entirely about the 'x' operator. Much cleaner than map.

      $sth -- again, style preference. I like to know what's going on. query, insert, etc...

      main() keeps me from using globals. I write all of my code with pragma strict, so using subs for all of the code requires 'my' prefixes.
      sub dbConnect and getData were used to facilate looping. While not a golfer, I do try to write concise code.
      Forgive me for having the hubris to write perl code that facilates pre-existing mySql code. This is perlmonks. Not mySqlmonks.

        I'm not sure why the {} notation for creating a hash ref isn't effective.

        My point about the extra procedures is that they didn't add any value to the DBI calls, ie they didn't remove any repetitive code. I find procedures like that a bad thing because instead of seeing a $sth->fetchall_arrayref I have to scroll down to see what the procedure actually does.

        I wasn't intending my comments to be a harsh critisism, I just wanted to point out there might be a better alternative.

        gav^

Re: dbCopy.pl
by redsquirrel (Hermit) on Feb 03, 2002 at 14:13 UTC
    I agree with each of gav^'s recommendations and would add one more:

    Your getData() subroutine could also be written this way. It may be just a matter of taste...

    sub getData { my ($sql,$dbHash) = @_; return $dbHash->{connect}->selectall_arrayref($sql); }

    --Dave