0

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

$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,如果字符串包含 a ',它将使用\'. 但是,在 PHPMyAdmin 的输出中,它将用连续'的两个单引号替换一个单引号''

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

4

1 回答 1

2

一行两个单引号的方法''是比较标准的SQL,所以更便携。

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

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

  • 您不处理 NULL:

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

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

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

你真的在重新发明轮子。

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

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

于 2013-08-15T01:47:24.170 回答