Creare un mysqldump con LIMIT

Potrebbe essere necessario a volte creare un campione dei dati di uno o più database, per esempio per poter chiedere assistenza a un consulente o per poter dare assistenza a un utente.

In questi casi, il classico strumento mysqldump non aiuta, perché fra le sue varie utilità non c’è quella di impostare una clausola LIMIT. È vero che si può filtrare con WHERE, ma questo è valido solo se si vogliono estrarre i dati di una tabella alla volta e anche in questo caso la clausola WHERE dovrebbe essere cambiata volta per volta.

Esistono alternative e la più spiccia è quella di creare un programma di estrazione in Perl, per poter prendere con un colpo solo la struttura e N record di tutte le tabelle di tutti i database.

Il semplice script che segue è una semplificazione (ma perfettamente funzionante) di uno strumento analogo che viene usato in StarData per acquisire campioni di dati dagli utenti.

Per limitare la portata dell’output, qualora non si volesse fornire la lista di tutti i database, è sufficiente eseguire questo script con i privilegi di un utente abilitato solo alla visione di alcuni database.


#!/usr/bin/perl -w
use strict;
use DBI;


my $host = 'localhost';
my $user = 'gmax'; # cambiare
my $password = ''; # cambiare
my $port = "3306";
my $limit = 1;
my $db = "test";
my $DSN = "DBI:mysql:$db;host=$host;port=$port;"
. "mysql_read_default_file=$ENV{HOME}/.my.cnf";


my $dbh =
DBI->connect( $DSN, $user, $password, { RaiseError => 1,
PrintError => 1 } )
or die "$DBI::errstr\n";


for my $db (@{$dbh->selectcol_arrayref("SHOW DATABASES})")
{
print STDERR "# ------ DATABASE $db\n";
print "# ------ DATABASE $db\n";
print "CREATE DATABASE IF NOT EXISTS $db;\n";
print "USE $db;\n";
for my $table (@{$dbh->selectcol_arrayref("SHOW TABLES FROM `$db`")})
{
print "# TABELLA ($db) $table\n";
print STDERR "# TABELLA ($db) $table\n";
my $sth = $dbh->prepare(qq{SHOW CREATE TABLE `$db`.`$table`});
$sth->execute ;
my ( $null, $create ) = $sth->fetchrow_array;
$sth->finish;
$create =~ s/(?<=CREATE TABLE)/ IF NOT EXISTS /; print " $create;\n"; $sth = $dbh->prepare(
"SELECT * FROM `$db`.`$table` LIMIT $limit");
$sth->execute;
while ( my $rec = $sth->fetchrow_arrayref )
{
print qq{INSERT INTO `$db`.`$table` (};
print join ",", map { "`$_`" } @{ $sth->NAME} };
print ") VALUES (";
print join ( ",", map( { $dbh->quote($_) } @$rec ) );
print ");\n";
}
}
}