Reputation: 25178
I need a way to easily export and then import data in a MySQL table from a remote server to my home server. I don't have direct access to the server, and no utilities such as phpMyAdmin are installed. I do, however, have the ability to put PHP scripts on the server.
How do I get at the data?
I ask this question purely to record my way to do it
Upvotes: 30
Views: 79713
Reputation: 4508
I found that I didn't have enough permissions for SELECT * INTO OUTFILE
.
But I was able to use enough php (iterating and imploding) to really cut down on the nested loops compared to other approaches.
$dbfile = tempnam(sys_get_temp_dir(),'sql');
// array_chunk, but for an iterable
function iter_chunk($iterable,$chunksize) {
foreach ( $iterable as $item ) {
$ret[] = $item;
if ( count($ret) >= $chunksize ) {
yield $ret;
$ret = array();
}
}
if ( count($ret) > 0 ) {
yield $ret;
}
}
function tupleFromArray($assocArr) {
return '('.implode(',',array_map(function($val) {
return '"'.addslashes($val).'"';
},array_values($assocArr))).')';
}
file_put_contents($dbfile,"\n-- Table $table --\n/*\n");
$description = $db->query("DESCRIBE `$table`");
$row = $description->fetch_assoc();
file_put_contents($dbfile,implode("\t",array_keys($row))."\n",FILE_APPEND);
foreach ( $description as $row ) {
file_put_contents($dbfile,implode("\t",array_values($row))."\n",FILE_APPEND);
}
file_put_contents($dbfile,"*/\n",FILE_APPEND);
file_put_contents($dbfile,"DROP TABLE IF EXISTS `$table`;\n",FILE_APPEND);
file_put_contents($dbfile,array_pop($db->query("SHOW CREATE TABLE `$table`")->fetch_row()),FILE_APPEND);
$ret = $db->query("SELECT * FROM `$table`");
$chunkedData = iter_chunk($ret,1023);
foreach ( $chunkedData as $chunk ) {
file_put_contents($dbfile, "\n\nINSERT INTO `$table` VALUES " . implode(',',array_map('tupleFromArray',$chunk)) . ";\n", FILE_APPEND );
}
readfile($dbfile);
unlink($dbfile);
If you have tables with foreign keys, this approach can still work if you drop
them in the correct order and then recreate them in the correct (reverse) order.
The CREATE
statement will create the foreign key dependency for you.
Go through SELECT * FROM information_schema.referential_constraints
to
determine that order.
If your foreign keys have a circular dependency, then there is no possible order to drop or create. In that case, you might be able to follow the lead of phpMyAdmin, which creates all of the foreign keys at the end. But this also means that you have to adjust the CREATE
statements.
Upvotes: 1
Reputation: 858
You could use SQL for this:
$file = 'backups/mytable.sql';
$result = mysql_query("SELECT * INTO OUTFILE '$file' FROM `##table##`");
Then just point a browser or FTP client at the directory/file (backups/mytable.sql). This is also a nice way to do incremental backups, given the filename a timestamp for example.
To get it back in to your DataBase from that file you can use:
$file = 'backups/mytable.sql';
$result = mysql_query("LOAD DATA INFILE '$file' INTO TABLE `##table##`");
The other option is to use PHP to invoke a system command on the server and run 'mysqldump':
$file = 'backups/mytable.sql';
system("mysqldump --opt -h ##databaseserver## -u ##username## -p ##password## ##database | gzip > ".$file);
Upvotes: 43
Reputation: 488
Here is a PHP
script I made which will backup all tables in your database. It is based on this http://davidwalsh.name/backup-mysql-database-php with some improvements. First of all it will correctly set up foreign key restrictions
.
In my set up the script will run on a certain day of the week, let's say Monday. In case it did not run on Monday, it will still run on Tuesday (for example), creating the .sql
file with the date of previous Monday, when it was supposed to run. It will erase .sql
file from 4 weeks ago, so it always keeps the last 4 backups. Here's the code:
<?php
backup_tables();
// backup all tables in db
function backup_tables()
{
$day_of_backup = 'Monday'; //possible values: `Monday` `Tuesday` `Wednesday` `Thursday` `Friday` `Saturday` `Sunday`
$backup_path = 'databases/'; //make sure it ends with "/"
$db_host = 'localhost';
$db_user = 'root';
$db_pass = '';
$db_name = 'movies_database_1';
//set the correct date for filename
if (date('l') == $day_of_backup) {
$date = date("Y-m-d");
} else {
//set $date to the date when last backup had to occur
$datetime1 = date_create($day_of_backup);
$date = date("Y-m-d", strtotime($day_of_backup.' -7 days'));
}
if (!file_exists($backup_path.$date.'-backup'.'.sql')) {
//connect to db
$link = mysqli_connect($db_host,$db_user,$db_pass);
mysqli_set_charset($link,'utf8');
mysqli_select_db($link,$db_name);
//get all of the tables
$tables = array();
$result = mysqli_query($link, 'SHOW TABLES');
while($row = mysqli_fetch_row($result))
{
$tables[] = $row[0];
}
//disable foreign keys (to avoid errors)
$return = 'SET FOREIGN_KEY_CHECKS=0;' . "\r\n";
$return.= 'SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";' . "\r\n";
$return.= 'SET AUTOCOMMIT=0;' . "\r\n";
$return.= 'START TRANSACTION;' . "\r\n";
//cycle through
foreach($tables as $table)
{
$result = mysqli_query($link, 'SELECT * FROM '.$table);
$num_fields = mysqli_num_fields($result);
$num_rows = mysqli_num_rows($result);
$i_row = 0;
//$return.= 'DROP TABLE '.$table.';';
$row2 = mysqli_fetch_row(mysqli_query($link,'SHOW CREATE TABLE '.$table));
$return.= "\n\n".$row2[1].";\n\n";
if ($num_rows !== 0) {
$row3 = mysqli_fetch_fields($result);
$return.= 'INSERT INTO '.$table.'( ';
foreach ($row3 as $th)
{
$return.= '`'.$th->name.'`, ';
}
$return = substr($return, 0, -2);
$return.= ' ) VALUES';
for ($i = 0; $i < $num_fields; $i++)
{
while($row = mysqli_fetch_row($result))
{
$return.="\n(";
for($j=0; $j<$num_fields; $j++)
{
$row[$j] = addslashes($row[$j]);
$row[$j] = preg_replace("#\n#","\\n",$row[$j]);
if (isset($row[$j])) { $return.= '"'.$row[$j].'"' ; } else { $return.= '""'; }
if ($j<($num_fields-1)) { $return.= ','; }
}
if (++$i_row == $num_rows) {
$return.= ");"; // last row
} else {
$return.= "),"; // not last row
}
}
}
}
$return.="\n\n\n";
}
// enable foreign keys
$return .= 'SET FOREIGN_KEY_CHECKS=1;' . "\r\n";
$return.= 'COMMIT;';
//set file path
if (!is_dir($backup_path)) {
mkdir($backup_path, 0755, true);
}
//delete old file
$old_date = date("Y-m-d", strtotime('-4 weeks', strtotime($date)));
$old_file = $backup_path.$old_date.'-backup'.'.sql';
if (file_exists($old_file)) unlink($old_file);
//save file
$handle = fopen($backup_path.$date.'-backup'.'.sql','w+');
fwrite($handle,$return);
fclose($handle);
}
}
?>
Upvotes: 3
Reputation: 56351
WORKING SOLUTION (latest version at: Export.php + Import.php )
EXPORT_TABLES("localhost","user","pass","db_name");
CODE:
//https://github.com/tazotodua/useful-php-scripts
function EXPORT_TABLES($host,$user,$pass,$name, $tables=false, $backup_name=false ){
$mysqli = new mysqli($host,$user,$pass,$name); $mysqli->select_db($name); $mysqli->query("SET NAMES 'utf8'");
$queryTables = $mysqli->query('SHOW TABLES'); while($row = $queryTables->fetch_row()) { $target_tables[] = $row[0]; } if($tables !== false) { $target_tables = array_intersect( $target_tables, $tables); }
foreach($target_tables as $table){
$result = $mysqli->query('SELECT * FROM '.$table); $fields_amount=$result->field_count; $rows_num=$mysqli->affected_rows; $res = $mysqli->query('SHOW CREATE TABLE '.$table); $TableMLine=$res->fetch_row();
$content = (!isset($content) ? '' : $content) . "\n\n".$TableMLine[1].";\n\n";
for ($i = 0, $st_counter = 0; $i < $fields_amount; $i++, $st_counter=0) {
while($row = $result->fetch_row()) { //when started (and every after 100 command cycle):
if ($st_counter%100 == 0 || $st_counter == 0 ) {$content .= "\nINSERT INTO ".$table." VALUES";}
$content .= "\n(";
for($j=0; $j<$fields_amount; $j++) { $row[$j] = str_replace("\n","\\n", addslashes($row[$j]) ); if (isset($row[$j])){$content .= '"'.$row[$j].'"' ; }else {$content .= '""';} if ($j<($fields_amount-1)){$content.= ',';} }
$content .=")";
//every after 100 command cycle [or at last line] ....p.s. but should be inserted 1 cycle eariler
if ( (($st_counter+1)%100==0 && $st_counter!=0) || $st_counter+1==$rows_num) {$content .= ";";} else {$content .= ",";} $st_counter=$st_counter+1;
}
} $content .="\n\n\n";
}
$backup_name = $backup_name ? $backup_name : $name."___(".date('H-i-s')."_".date('d-m-Y').")__rand".rand(1,11111111).".sql";
header('Content-Type: application/octet-stream'); header("Content-Transfer-Encoding: Binary"); header("Content-disposition: attachment; filename=\"".$backup_name."\""); echo $content; exit;
}
Upvotes: 9
Reputation: 2830
You should also consider phpMinAdmin which is only one file, so its easy to upload and setup.
Upvotes: 14
Reputation: 2909
You might consider looking at: http://www.webyog.com This is a great GUI admin tool, and they have a really neat HTTP-Tunneling feature (I'm not sure if this is only in enterprise which costs a few bucks).
Basically you upload a script they provide into your webspace (php script) and point sqlyog manager to it and you can access the database(s). It uses this script to tunnel/proxy the requests/queries between your home client and the server.
I know at least 1 person who uses this method with great results.
Upvotes: 4
Reputation: 17734
I use mysqldump via the command line :
exec("mysqldump sourceDatabase -uUsername -p'password' > outputFilename.sql");
Then you just download the resulting file and your done.
Upvotes: -1
Reputation: 5437
If you have FTP/SFTP access you could just go ahead and upload phpMyAdmin yourself.
I'm using this little package to make automated mysql backups from a server I only have FTP access to:
http://www.taw24.de/download/pafiledb.php?PHPSESSID=b48001ea004aacd86f5643a72feb2829&action=viewfile&fid=43&id=1
The site is in german but the download has some english documentation as well.
A quick google also turns up this, but I have not used it myself:
http://snipplr.com/view/173/mysql-dump/
Upvotes: 4
Reputation: 25178
I did it by exporting to CSV, and then importing with whatever utility is available. I quite like the use of the php://output stream.
$result = $db_con->query('SELECT * FROM `some_table`');
$fp = fopen('php://output', 'w');
if ($fp && $result) {
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="export.csv"');
while ($row = $result->fetch_array(MYSQLI_NUM)) {
fputcsv($fp, array_values($row));
}
die;
}
Upvotes: 18