因此,我使用以下代码备份数据库:

$rows = $this->_getDb()->fetchAll("SELECT * FROM $table");

foreach ($rows AS $row)
{
    foreach ($row AS &$value)
    {
        if (!is_numeric($value))
        {
            $value = "'".addcslashes($value, "'\\")."'";
            $value = str_replace("\n", '\n', $value);
        }
    }

    if (!$count)
    {
        $output .= "INSERT INTO `$table` (" .implode(', ', $columns). ") VALUES";
    }

    $count++;
    $output .= "\n(" .implode(', ', $row). "),";

    if ($count >= $limit)
    {
        $count = 0;
        $output = preg_replace('#,$#', ";\n\n", $output);
    }
}

$output = preg_replace('#,$#', ";\n\n", $output);


这似乎工作得很好...但是我正在将输出与从PHPMyAdmin获得的输出进行比较,并且注意到一些细微的差异。对于我的代码,由于我使用addcslashes的方式,如果字符串包含',它将使用\'对其进行转义。但是,在PHPMyAdmin的输出中,它将改为用两个单引号'连续替换一个''

真的有区别吗?请查看我转义非数字字段的方式,并告诉我是否有更好的方法。

最佳答案

连续两个单引号''的方法是更标准的SQL,因此更可移植。

甚至MySQL也支持称为NO_BACKSLASH_ESCAPESSQL_MODE,如果您尝试将备份导入启用了该模式的服务器,则会使反斜杠处理的字符串无效。

但是我必须添加注释,以使您的数据库备份方法充满其他问题。


您不处理NULL:

if (!is_numeric($value))

这不会处理需要定界的列名,因为它们可能与SQL保留字冲突:

$output .= "INSERT INTO `$table` (" .implode(', ', $columns). ") VALUES";

如果您的任何表中都有数百万行,那么尝试以一系列INSERT语句的形式在单个字符串中存储该表的全部内容,将超出PHP的最大内存限制:

$output .= "\n(" .implode(', ', $row). "),";

您仅显示脚本的一部分,但也可能无法正确处理二进制字符串,字符集,触发器,存储的例程,视图,表选项等。


您真的在重新发明轮子。

我看过过去的问题,人们尝试做您正在做的事情,但是很难做到正确:


PHP Database Dump Script - are there any issues?
Why is my database backup script not working in php?


仅使用PHP中的shell_exec()来调用mysqldumpmydumper会更好地利用您的时间。

10-04 21:41
查看更多