PHP脚本创建一个空的SQL文件

时间:2015-10-19 19:21:00

标签: php mysql sql

所以这对我来说是新的。当David Walsh使用这个MySQL数据库PHP脚本时,我在运行它时得到一个空的SQL文件。

<?php
backup_tables('localhost','username','password','blog');

/* backup the db OR just a table */
function backup_tables($host,$user,$pass,$name,$tables = '*')
{
    $return = '';
    $link = mysql_connect($host,$user,$pass);
    mysql_select_db($name,$link);

    //get all of the tables
    if($tables == '*')
    {
        $tables = array();
        $result = mysql_query('SHOW TABLES');
        while($row = mysql_fetch_row($result))
        {
            $tables[] = $row[0];
        }
    }
    else
    {
        $tables = is_array($tables) ? $tables : explode(',',$tables);
    }

    //cycle through
    foreach($tables as $table)
    {
        $result = mysql_query('SELECT * FROM '.$table);
        $num_fields = mysql_num_fields($result);

        $return.= 'DROP TABLE '.$table.';';
        $row2 = mysql_fetch_row(mysql_query('SHOW CREATE TABLE '.$table));
        $return.= "\n\n".$row2[1].";\n\n";

        for ($i = 0; $i < $num_fields; $i++) 
        {
            while($row = mysql_fetch_row($result))
            {
                $return.= 'INSERT INTO '.$table.' VALUES(';
                for($j=0; $j<$num_fields; $j++) 
                {
                    $row[$j] = addslashes($row[$j]);
                    $row[$j] = ereg_replace("\n","\\n",$row[$j]);
                    if (isset($row[$j])) { $return.= '"'.$row[$j].'"' ; } else { $return.= '""'; }
                    if ($j<($num_fields-1)) { $return.= ','; }
                }
                $return.= ");\n";
            }
        }
        $return.="\n\n\n";
    }

    //save file
    $handle = fopen('db-backup-'.time().'-'.(md5(implode(',',$tables))).'.sql','w+');
    fwrite($handle,$return);
    fclose($handle);
    mysql_close($link);
}
?>

当我理解代码时,我输入了数据库名称,其中博客位于顶部的函数backup_tables()中。

为什么脚本会创建一个空的SQL文件?

7 个答案:

答案 0 :(得分:4)

我尝试过这个脚本,它对我有用,虽然有一些错误和一些折旧警告。

要保存文件,请确保脚本所在的目录具有写入权限。

chmod 0777 /home/site/dir

要阻止Undefined variable: return通知,请添加以下代码

$return = '';

就在这一行之前

$link = mysql_connect($host,$user,$pass);

并且 - 我知道这似乎很明显 - 但请确保您连接到正确的数据库,或者您没有数据库名称的拼写错误。

backup_tables('localhost','myUsername','myPassword','myDatabase');

最后:确保数据库有表。我在数据库中没有表运行它来查看发生了什么 - 它吐了一个空白文档。就像你描述的那样。 :)

答案 1 :(得分:4)

有一种更好的方法可以做到这一点,即mysqldump。它是为了创建表的备份而构建的,它比php快得多。您只需在终端中运行以下命令:

mysqldump -h localhost -u root -p --result-file ~/backup.sql my_database

如果您只想备份几张桌子,可以这样做:

mysqldump -h localhost -u root -p --result-file ~/backup.sql my_database table_a table_b

您可以使用更多选项,因此我不会列出它们,但您可以在此处阅读它们:

https://dev.mysql.com/doc/refman/5.1/en/mysqldump.html

如果您需要php来执行此操作,您可以通过exec()或其他类似方法执行此操作:

exec("mysqldump -h $host -u $user -p$pass --result-file ~/$file $database $tables");

答案 2 :(得分:2)

我没有在。='DROP行之前的任何地方看到$ return。我有涉及未定义变量的错误。在foreach()之上添加$ return ='';

答案 3 :(得分:2)

要添加到timgavin的答案,您还可以为此脚本添加压缩,只需添加

即可
$compression = true;

到顶部

并改变底部 从

$handle = fopen('db-backup-'.time().'-'.(md5(implode(',',$tables))).'.sql','w+');
fwrite($handle,$return);
fclose($handle);
mysql_close($link);

if ($compression) {
    $zp = gzopen($BACKUP_PATH . 'db-backup-'.time().'-'.(md5(implode(',',$tables))).'.sql.gz', "w9");
    gzwrite($zp, $return);
    gzclose($zp);
} else {
    $handle = fopen($BACKUP_PATH . 'db-backup-'.time().'-'.(md5(implode(',',$tables))).'.sql','w+');
    fwrite($handle,$return);
    fclose($handle);
}

另一个选项由his blog上的mohd_anas以及github

解释

答案 4 :(得分:1)

如果您使用表名运行脚本,它可以正常工作。你应该添加$ return ='';到第26行。 backup_tables('localhost','root','arcd','unilicadb', 'fa_university');

如果您使用通配符运行backup_tables('localhost','root','arcd','unilicadb', '*');,则可能会遇到内存错误,以防您拥有较大的数据库。

“致命错误:允许的内存大小为134217728字节耗尽(试图分配34399640字节)”

尝试添加error_reporting(E_ALL);

答案 5 :(得分:1)

backup_tables('localhost','root','','dbname');

/* backup the db OR just a table */
function backup_tables($host,$user,$pass,$name,$tables = '*')
{
    $return = '';
    $link = mysqli_connect($host,$user,$pass, $name);
    //get all of the tables
    if($tables == '*')
    {
        $tables = array();
        $result = mysqli_query($link, 'SHOW TABLES');
        while($row = mysqli_fetch_row($result))
        {
            $tables[] = $row[0];
        }
    }
    else
    {
        $tables = is_array($tables) ? $tables : explode(',',$tables);
    }

    //cycle through
    foreach($tables as $table)
    {
        $result = mysqli_query($link, 'SELECT * FROM '.$table);
        $num_fields = mysqli_num_fields($result);

        $return.= 'DROP TABLE '.$table.';';
        $tableResult = mysqli_query($link, 'SHOW CREATE TABLE '.$table);
        $row2 = mysqli_fetch_row($tableResult);
        $return.= "\n\n".$row2[1].";\n\n";

        for ($i = 0; $i < $num_fields; $i++) 
        {
            while($row = mysqli_fetch_row($result))
            {
                $return.= 'INSERT INTO '.$table.' VALUES(';
                for($j=0; $j<$num_fields; $j++) 
                {
                    $row[$j] = addslashes($row[$j]);
                    $row[$j] = str_replace("\n","\\n",$row[$j]);
                    if (isset($row[$j])) { $return.= '"'.$row[$j].'"' ; } else { $return.= '""'; }
                    if ($j<($num_fields-1)) { $return.= ','; }
                }
                $return.= ");\n";
            }
        }
        $return.="\n\n\n";
    }

    //save file
    $handle = fopen('db-backup-'.time().'-'.(md5(implode(',',$tables))).'.sql','w+');
    fwrite($handle,$return);
    fclose($handle);
    mysqli_close($link);
}

答案 6 :(得分:1)

我从一开始就一直关注你的问题,我做了我的研究,发现你的问题很有意思。

通过php代码备份mysql的大多数解决方案都已过时,并且在当今的环境中存在问题。因此,我很想知道是否有任何更新和有用的一次。我的计划是,如果我找不到一个,那么我想开发一个。

但我找到了一个解决方案并且有效。我通过导出和重新导入表来测试它。我想你会喜欢它。

在转到代码之前,我有以下注释:

  1. 关于David Walsh,您关注的代码和教程是从2008年开始使用的MySQL,现已弃用。下面的代码可能使用MySQLi。
  2. 当您运行代码时,它将为您提供可下载的备份文件。您可以将文件传递到安全的远程目标,如服务器,云存储(dropbox等)。
  3. 定期运行备份功能,具体取决于您的操作系统,环境,策略以及您希望如何采用该方法。在大多数情况下,CRON是安排它每晚运行一次或类似的事情的解决方案,有关于该在线的教程和有用信息。
  4. 这个函数的软件只会在localhost上进行备份,因为大多数主机提供程序都阻止了远程mysql访问(所以这个函数不能备份远程mysql表)。
  5. 在开始和测试时,可以使用root用户名,但是当它工作时,我建议你创建一个用户名和密码特定访问你想要备份的表。
  6. 注意:代码在代码所有者的page上找到,我添加了额外的代码行,以使其适用于OP。

    非常重要的说明: 取决于您的服务器资源和容量和数据库大小,执行此类代码可能需要一些时间,特别是如果您有共享主机,则需要将执行时间延长至300秒(5分钟),并且应在低负载时间内执行备份。 最糟糕的情况是,如果代码阻止了该部分,您可能需要请求主机提供商延长执行时间。

    工作代码

    <?php
    
    define("MAX_EXECUTION_TIME", 100); // seconds
    
    $timeline = time() + MAX_EXECUTION_TIME;
    
    EXPORT_TABLES('localhost', 'root', '', 'blog');
    
    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);
        }
        try
        {
            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";
            }
        } catch (Exception $e)
        {
            echo 'Caught exception: ', $e->getMessage(), "\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;
    }
    
    ?>