核心邏輯
- 逐行讀取 .sql 檔,累積至遇到分號
; 視為一條完整 SQL。
- 跳過註解行(
-- 開頭)。
- 逐條
mysqli_query() 執行,避免單一巨大查詢導致記憶體/逾時問題。
完整程式碼
<?php
set_time_limit(0); // 移除執行時間限制
$mysqli = new mysqli('localhost', 'user', 'pass', 'db');
$mysqli->set_charset('utf8mb4');
$fp = fopen('backup.sql', 'r') or die('無法開啟 SQL 檔');
$sql = '';
while (($line = fgets($fp, 40960)) !== false) {
$line = trim($line);
if ($line === '' || str_starts_with($line, '--')) continue;
$sql .= $line . "\n";
if (substr($line, -1) === ';') {
if (!$mysqli->query($sql)) {
error_log('SQL 執行失敗: ' . $mysqli->error . ' | SQL: ' . $sql);
}
$sql = '';
}
}
fclose($fp);
$mysqli->close();
echo '匯入完成';
?>
注意事項
- 此法無法處理「分號出現在字串/觸發器/預存程序內部」的情況。生產環境建議用
mysql -u root -p db < backup.sql 命令列工具。
- 大檔案可改用
mysqli_multi_query() 批次送入,但需自行處理結果集。
- PHP 記憶體限制:
ini_set('memory_limit', '512M')。