[英]Backing up MySQL DB… Proper way to escape strings?
所以我使用以下代碼備份我的數據庫:
$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的支持SQL_MODE稱為NO_BACKSLASH_ESCAPES
這將使您的反斜杠處理字符串無效的,如果你嘗試將備份導入到啟用了該模式的服務器。
但我必須添加注釋,以明確表示備份數據庫的方法充滿了其他問題。
你不處理NULL:
if (!is_numeric($value))
這不處理需要分隔的列名,因為它們可能與SQL保留字沖突:
$output .= "INSERT INTO `$table` (" .implode(', ', $columns). ") VALUES";
如果您的任何tabes中有數百萬行,那么嘗試以單個字符串中的一系列INSERT語句的形式存儲該表的整個內容將超過PHP的最大內存限制:
$output .= "\\n(" .implode(', ', $row). "),";
您只顯示腳本的一部分,但它也可能無法正確處理二進制字符串,字符集,觸發器,存儲例程,視圖,表選項等。
你真的在重新發明輪子。
我已經看到過去的問題,人們試圖做你正在做的事情,但很難做到正確:
使用PHP中的shell_exec()來調用mysqldump或mydumper會更好地利用你的時間。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.