phpMyAdmin 瓶頸
- 匯入失敗:PHP
upload_max_filesize/post_max_size 預設 2MB,大檔無法上傳。
- 單引號逸出問題:匯出 SQL 檔含特殊字元時,匯入易報語法錯誤。
解決架構:結構與資料分離
- 結構:仍用 phpMyAdmin 匯出
CREATE TABLE 等 DDL。
- 資料:自製腳本以「每行一欄位、特殊字元編碼」格式匯出純文字檔,匯入時再還原。
匯出腳本 export.php
<?php
// 用法:export.php?table=tablename
$table = $_GET['table']; if (!$table) exit;
mysql_connect("localhost", "user", "pass");
mysql_select_db("dbname");
$res = mysql_query("SELECT * FROM `$table`");
if (mysql_num_rows($res) == 0) exit;
echo "開始轉換資料到文字檔...
";
$handle = fopen("$table.txt", "w");
$num_fields = mysql_num_fields($res);
fputs($handle, $num_fields . "\r\n");
for ($k = 0; $k < mysql_num_rows($res); $k++) {
$row = mysql_fetch_row($res);
for ($i = 0; $i < $num_fields; $i++) {
// 將換行統一編碼為特殊標記
$row[$i] = str_replace("\r\n", "&&php2000mysqlreturn&&", $row[$i]);
$row[$i] = str_replace("\n", "&&php2000mysqlreturn&&", $row[$i]);
fputs($handle, $row[$i] . "\r\n");
}
// 每筆結束標記
fputs($handle, "------- php2000 dump data program V1.0 for MySQL --------\r\n");
}
fclose($handle);
echo "ok";
?>
匯入腳本 import.php
<?php
$table = $_GET['table']; if (!$table) exit;
mysql_connect("localhost", "user", "pass");
mysql_select_db("dbname");
$lines = file("$table.txt");
$num_fields = (int)trim($lines[0]);
for ($k = 1; $k < count($lines); $k += $num_fields + 1) {
$values = [];
for ($i = 0; $i < $num_fields; $i++) {
$raw = trim($lines[$k + $i]);
$val = str_replace("&&php2000mysqlreturn&&", "\r\n", $raw);
$values[] = "'" . addslashes($val) . "'";
}
$sql = "INSERT INTO `$table` VALUES (" . implode(',', $values) . ")";
mysql_query($sql);
echo mysql_error() . " $k ";
}
echo "ok";
?>
操作流程
- 伺服器執行
export.php 產生 tablename.txt。
- FTP 下載文字檔到本地(或傳至另一台伺服器)。
- 目標庫用 phpMyAdmin 匯入結構(DDL)。
- 目標伺服器上傳文字檔,執行
import.php 匯入資料。
注意事項與改進
file() 會一次讀入整檔記憶體,超大檔(>100MB)請改用 fopen() + fgets() 逐行處理。
- 編碼標記
&&php2000mysqlreturn&& 需確保不與實際資料衝突,建議改用 Base64 或 JSON 編碼更穩健。
- 可擴充為多執行緒、支援交易批次提交、斷點續傳。
- 現代專案建議直接使用
mysqldump --single-transaction --quick + mysql 管線,或 LOAD DATA INFILE,效能更佳且無需自製腳本。