首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

PHP 解析執行 SQL 文件實現資料庫遷移上傳工具

     編輯:MySQL 資料庫相關知識

前言

資料庫遷移常需將 mysqldump 導出的 SQL 文件在目標服務器執行。傳統方式:上傳文件 → SSH 登入 → mysql < file.sql。本文實現一個純 PHP Web 工具:上傳 SQL 文件 → 自動解析分割語句 → 逐條執行 → 即時反饋結果,免去手動上傳與命令行操作。

一、核心邏輯:SQL 語句分割策略

mysqldump 輸出特徵:

  • 單行註釋以 # 或 -- 開頭。
  • DROP TABLE、CREATE TABLE 等 DDL 單獨成行,以分號結尾。
  • INSERT INTO ... VALUES (...),(...); 多行數據以 ); 結尾。

解析規則:

  1. 逐行讀取,跳過註釋行。
  2. 累積行內容至緩衝區 $sql。
  3. 遇到 DROP 開頭或行尾 ); 視為一條完整語句,執行並清空緩衝區。

二、完整實現代碼 (import_sql.php)

<?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(最快、最穩)。
  • mysqldump --tab + mysqlimport:大數據量並行導入。
  • ETL 工具:DataX、Kettle、Canal 等支援增量同步。

五、總結

本文提供了一個輕量級 PHP SQL 執行工具,適用於中小型 SQL 文件(<50MB)、無存儲過程、Web 運維場景。核心在於按 mysqldump 輸出格式精準分割語句。生產環境大數據遷移仍建議使用原生命令行或專業 ETL 工具。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved