資料庫遷移常需將 mysqldump 導出的 SQL 文件在目標服務器執行。傳統方式:上傳文件 → SSH 登入 → mysql < file.sql。本文實現一個純 PHP Web 工具:上傳 SQL 文件 → 自動解析分割語句 → 逐條執行 → 即時反饋結果,免去手動上傳與命令行操作。
mysqldump 輸出特徵:
# 或 -- 開頭。DROP TABLE、CREATE TABLE 等 DDL 單獨成行,以分號結尾。INSERT INTO ... VALUES (...),(...); 多行數據以 ); 結尾。解析規則:
$sql。DROP 開頭或行尾 ); 視為一條完整語句,執行並清空緩衝區。<?php
// 配置資料庫連接
$host = 'localhost'; $user = 'root'; $pass = 'password'; $db = 'target_db';
$conn = mysqli_connect($host, $user, $pass, $db) or die('連接失敗');
mysqli_set_charset($conn, 'utf8mb4');
if (isset($_POST['go']) && isset($_FILES['sql_file'])) {
$file = $_FILES['sql_file']['tmp_name'];
$name = $_FILES['sql_file']['name'];
echo "正在執行: $name ...<br>";
$fp = fopen($file, 'r');
$sql = '';
$success = true;
$lineNum = 0;
while (($line = fgets($fp, 8192)) !== false) {
$lineNum++;
$trimmed = trim($line);
// 跳過註釋
if (strpos($trimmed, '#') === 0 || strpos($trimmed, '--') === 0) continue;
$sql .= $line;
// 判斷語句結束
$isDrop = (strpos(strtoupper($trimmed), 'DROP') === 0);
$endsWithSemicolon = (substr(rtrim($trimmed), -1) === ';');
$endsWithInsertClose = (substr(rtrim($trimmed), -2) === ');');
if ($isDrop || $endsWithSemicolon || $endsWithInsertClose) {
$sql = rtrim($sql, ";\r\n"); // 去除尾部分號換行
if ($sql) {
if (!mysqli_query($conn, $sql)) {
echo "<font color='red'>第 $lineNum 行執行失敗: </font>" . mysqli_error($conn) . "<br>";
echo "<pre>$sql</pre>";
$success = false;
break;
} else {
echo ($isDrop ? "DROP 執行成功" : "INSERT/其他 執行成功") . "<br>";
}
$sql = '';
}
}
}
fclose($fp);
if ($success) echo "<b>$name 執行完畢,請驗證數據</b>";
} else {
?>
<form method="post" enctype="multipart/form-data">
<input type="file" name="sql_file" accept=".sql" required>
<input type="submit" name="go" value="執行 SQL 文件">
</form>
<?php } ?>
| 問題 | 解決方案 |
|---|---|
| 超大文件導致 PHP 逾時/記憶體溢出 | 設置 set_time_limit(0)、ini_set('memory_limit','512M');分批提交事務 |
| SQL 語句包含分號(如存儲過程、Trigger) | 改用 DELIMITER 解析或直接調用 mysql 客戶端(exec()) |
| 編碼不匹配導致亂碼 | 檢測文件編碼 mb_detect_encoding,轉為 utf8mb4 後執行 |
| 外鍵約束導入失敗 | 執行前 SET FOREIGN_KEY_CHECKS=0,結束後恢復 |
| 無進度反饋 | 配合 AJAX 輪詢或 WebSocket 實時顯示進度條 |
mysql -h host -u user -p db < file.sql(最快、最穩)。本文提供了一個輕量級 PHP SQL 執行工具,適用於中小型 SQL 文件(<50MB)、無存儲過程、Web 運維場景。核心在於按 mysqldump 輸出格式精準分割語句。生產環境大數據遷移仍建議使用原生命令行或專業 ETL 工具。