在專案部署、資料遷移或自動化測試中,常需透過 PHP 程式化方式匯入 .sql 檔案。本文詳解核心思路,並提供一個支援事務、註釋過濾、錯誤回滾的 ImportSql 類,開箱即用。
file_get_contents() 將整個 SQL 載入字串。-- 單行註釋與 /* */ 多行註釋。;\n 為界拆分成陣列,並 trim() 去除首尾空白。<?php
/**
* SQL 匯入工具類
* 支援:註釋過濾、事務執行、錯誤定位、多語句批次匯入
*/
class ImportSql
{
/** @var resource 資料庫連接資源 */
protected $connect = null;
/** @var bool 資料庫選擇結果 */
protected $db = null;
/** @var string 原始 SQL 內容 */
public $sqlFile = "";
/** @var array 解析後的 SQL 陣列 */
public $sqlArr = array();
/**
* 建構子:建立資料庫連線
* @param string $host 主機
* @param string $user 使用者
* @param string $pw 密碼
* @param string $db_name 資料庫名稱
*/
public function __construct($host, $user, $pw, $db_name)
{
$this->connect = mysql_connect($host, $user, $pw)
or die("連線失敗: " . mysql_error());
$this->db = mysql_select_db($db_name, $this->connect)
or die("選擇資料庫失敗: " . mysql_error());
}
/**
* 匯入 SQL 檔案
* @param string $url 檔案路徑
* @return bool 成功回傳 true
*/
public function Import($url)
{
if (!file_exists($url)) exit("檔案不存在!");
$this->sqlFile = file_get_contents($url);
if (!$this->sqlFile) exit("讀取檔案錯誤!");
$this->GetSqlArr();
return $this->RunSql();
}
/** 解析 SQL 字串為陣列 */
public function GetSqlArr()
{
$str = $this->sqlFile;
// 移除單行註釋
$str = preg_replace('/--.*/i', '', $str);
// 移除多行註釋
$str = preg_replace('/\/\*.*\*\/(\;)?/i', '', $str);
// 分割語句
$str = explode(";\n", $str);
foreach ($str as $v) {
$v = trim($v);
if (empty($v)) continue;
$this->sqlArr[] = $v;
}
}
/** 事務執行所有 SQL */
public function RunSql()
{
if (mysql_query('BEGIN')) {
foreach ($this->sqlArr as $k => $v) {
if (!mysql_query($v)) {
mysql_query('ROLLBACK');
exit("SQL 執行錯誤:第 " . $k . " 行 - " . mysql_error());
}
}
mysql_query('COMMIT');
return true;
} else {
exit('無法開啟事務!');
}
}
}
// ---------- 使用範例 ----------
header("Content-type:text/html;charset=utf-8");
$sql = new ImportSql("localhost", "root", "", "log_db");
$rst = $sql->Import("./log_db.sql");
if ($rst) echo "匯入成功!";
?>
preg_replace('/--.*/i', '', $str) 處理單行;preg_replace('/\/\*.*\*\/(\;)?/i', '', $str) 處理多行,i 忽略大小寫。;\n 而非單純 ;,避免誤切預存程序或觸發器內部的分號。上述範例使用已棄用的 mysql_* 函數。實際專案建議改用 PDO 或 mysqli,並採用預處理語句防止注入。核心邏輯(註釋過濾、分割、事務)保持不變,只需替換資料庫操作層即可。
將此類封裝為 Composer 套件或專案共用 Library,即可在部署腳本、單元測試、CI/CD 流程中複用,大幅提升資料庫遷移效率。