备份MySQL DB ...正确的方法来逃避字符串?

时间:2013-08-15 01:31:11

标签: php mysql database-backups

所以我使用以下代码备份我的数据库:

$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的输出中,它将用一行中的两个单引号'替换单个''

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

1 个答案:

答案 0 :(得分:2)

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

即使MySQL支持名为NO_BACKSLASH_ESCAPES的{​​{3}},如果您尝试将备份导入启用了该模式的服务器,也会使反斜杠处理的字符串无效。

但我必须添加注释,以明确表示备份数据库的方法充满了其他问题。

  • 您不处理NULL:

    if (!is_numeric($value))
    
  • 这不处理需要分隔的列名,因为它们可能与SQL保留字冲突:

    $output .= "INSERT INTO `$table` (" .implode(', ', $columns). ") VALUES";
    
  • 如果您的任何标签页中有数百万行,尝试以单个字符串中的一系列INSERT语句的形式存储该表的整个内容将超过PHP的最大内存限制:

    $output .= "\n(" .implode(', ', $row). "),";
    
  • 您只显示部分脚本,但它也可能无法正确处理二进制字符串,字符集,触发器,存储例程,视图,表格选项等。

你真的在重新发明轮子。

我已经看到过去的问题,人们会尝试做你正在做的事情,但很难做到正确:

使用PHP中的Why is my database backup script not working in php?拨打shell_exec()mysqldump可以更好地利用您的时间。