首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 匯入 CSV 檔案至 MySQL 資料庫完整教學

     編輯:PHP 相關知識

PHP CSV 匯入 MySQL 完整實作指南

本文詳細說明如何使用 PHP 內建函數 fgetcsv() 解析 CSV 檔案,並將資料批次匯入 MySQL 資料庫。涵蓋檔案上傳、編碼處理、資料驗證、錯誤處理、進度回饋等完整流程,適合會員匯入、商品批次更新、報表資料導入等場景。

核心流程架構

  1. HTML 表單上傳 CSV 檔案 (enctype="multipart/form-data")
  2. PHP 接收暫存檔,移動至可存取路徑
  3. 使用 fopen() + fgetcsv() 逐行讀取解析
  4. 資料清洗與驗證 (編碼轉換、欄位對應、空值處理)
  5. 使用 Prepared Statements 批次寫入資料庫
  6. 交易控制確保資料一致性
  7. 回報匯入結果 (成功筆數、失敗筆數、錯誤明細)

完整程式碼實作 (含安全性強化)

 10 * 1024 * 1024) { // 10MB 限制
        $errors[] = '檔案過大,請勿超過 10MB';
    }
    $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
    if ($ext !== 'csv') {
        $errors[] = '僅支援 .csv 副檔名';
    }
    
    if (!empty($errors)) {
        die('
  • ' . implode('
  • ', $errors) . '
'); } // 移動暫存檔到安全位置 $uploadDir = sys_get_temp_dir() . '/csv_imports/'; if (!is_dir($uploadDir)) mkdir($uploadDir, 0755, true); $tmpName = $uploadDir . uniqid('csv_') . '.csv'; if (!move_uploaded_file($file['tmp_name'], $tmpName)) { die('無法儲存上傳檔案'); } // ===== 2. 資料庫連線 (PDO + 例外模式) ===== try { $pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=$charset", $user, $pass, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, // 使用真實 Prepared Statements ]); } catch (PDOException $e) { @unlink($tmpName); die('資料庫連線失敗: ' . $e->getMessage()); } // ===== 3. 開啟 CSV 檔案 (自動偵測編碼) ===== $handle = fopen($tmpName, 'r'); if (!$handle) { @unlink($tmpName); die('無法開啟 CSV 檔案'); } // 嘗試偵測 BOM 與編碼 $firstLine = fgets($handle, 4096); rewind($handle); // 簡易 BOM 檢測 $bom = ''; if (strncmp($firstLine, "\xEF\xBB\xBF", 3) === 0) { $bom = 'UTF-8'; } elseif (strncmp($firstLine, "\xFF\xFE", 2) === 0 || strncmp($firstLine, "\xFE\xFF", 2) === 0) { $bom = 'UTF-16'; } // ===== 4. 讀取標題列 (對應欄位) ===== $headers = fgetcsv($handle, 4096, ',', '"', '\\'); if (!$headers) { fclose($handle); @unlink($tmpName); die('CSV 檔案為空或格式錯誤'); } // 正規化標題 (去除 BOM、空白、特殊字元) $headers = array_map(function($h) { $h = trim($h); $h = preg_replace('/^\xEF\xBB\xBF/', '', $h); // 移除 UTF-8 BOM return $h; }, $headers); echo "

偵測到欄位: " . implode(', ', $headers) . "

"; // ===== 5. 準備 Prepared Statement ===== // 假設資料表欄位: name, classes, a_time, college, notify, receiver, r_time, handler $placeholders = implode(',', array_fill(0, count($headers), '?')); $columns = implode(',', array_map(function($c) { return "`$c`"; }, $headers)); $sql = "INSERT INTO `$targetTable` ($columns) VALUES ($placeholders)"; $stmt = $pdo->prepare($sql); // ===== 6. 批次匯入主迴圈 ===== $pdo->beginTransaction(); $success = 0; $failed = 0; $errors = []; $rowNum = 1; // 已讀標題列,資料從第 2 列開始 while (($data = fgetcsv($handle, 4096, ',', '"', '\\')) !== FALSE) { $rowNum++; // 跳過空行 if (count(array_filter($data)) === 0) continue; // 欄位數驗證 if (count($data) !== count($headers)) { $failed++; $errors[] = "第 $rowNum 行: 欄位數不符 (預期 " . count($headers) . ", 實際 " . count($data) . ")"; if ($failed > 100) break; // 錯誤過多停止 continue; } // 編碼轉換 (若 CSV 非 UTF-8) // $data = array_map(function($v) { return iconv('BIG5', 'UTF-8//IGNORE', $v); }, $data); try { $stmt->execute($data); $success++; // 批次提交 if ($success % $batchSize === 0) { $pdo->commit(); $pdo->beginTransaction(); echo ""; ob_flush(); flush(); } } catch (PDOException $e) { $failed++; $errors[] = "第 $rowNum 行: " . $e->getMessage(); } } // 提交剩餘交易 $pdo->commit(); fclose($handle); @unlink($tmpName); // ===== 7. 結果報告 ===== echo "
"; echo "

匯入完成

"; echo "

成功: $success 筆

"; echo "

失敗: $failed 筆

"; echo "

總計: " . ($success + $failed) . " 筆

"; if (!empty($errors)) { echo "
錯誤明細 (前 50 筆)
    "; foreach (array_slice($errors, 0, 50) as $err) { echo "
  • " . htmlspecialchars($err) . "
  • "; } echo "
"; } echo "
"; exit; } ?>

HTML 上傳表單




    
    CSV 匯入系統
    


    

CSV 資料匯入

檔案需求

  • 格式: UTF-8 編碼 CSV (逗號分隔)
  • 第一列必須為標題列,欄位名稱對應資料表欄位
  • 支援欄位: name, classes, a_time, college, notify, receiver, r_time, handler
  • 檔案大小限制: 10MB
  • 日期格式建議: YYYY-MM-DD HH:MM:SS

CSV 檔案範例格式

name,classes,a_time,college,notify,receiver,r_time,handler
張三,一年甲班,2024-01-15 08:30:00,資訊學院,系統通知,李老師,2024-01-15 09:00:00,教務處
李四,二年乙班,2024-01-16 10:00:00,管理學院,郵件通知,王主任,2024-01-16 10:30:00,學務處
王五,三年丙班,2024-01-17 14:00:00,工學院,簡訊通知,趙導師,2024-01-17 14:30:00,總務處

效能優化建議

場景優化策略
大量資料 (>10萬筆)使用 LOAD DATA INFILE SQL 指令,比 PHP 逐行插入快 10-50 倍
記憶體不足分批讀取、分批提交交易、避免一次載入整個檔案
頻繁匯入建立匯入佇列 + 背景 Worker (Gearman/Redis Queue/Laravel Jobs)
需更新而非新增使用 INSERT ... ON DUPLICATE KEY UPDATE 或 REPLACE INTO

常見問題排查

Q: 匯入後中文變亂碼
A: 確認 CSV 檔案為 UTF-8 編碼 (含 BOM 最佳)、資料庫連線 charset=utf8mb4、資料表欄位 collation=utf8mb4_unicode_ci。必要時在讀取後用 iconv('BIG5', 'UTF-8//IGNORE', $v) 轉碼。
Q: 日期欄位匯入失敗
A: MySQL 要求日期格式為 YYYY-MM-DD HH:MM:SS。CSV 中若為其他格式需先轉換,或在 SQL 中使用 STR_TO_DATE()。
Q: 欄位包含逗號/換行/雙引號
A: 標準 CSV 會用雙引號包裹此類欄位,fgetcsv() 可正確解析。確保 CSV 產生工具符合 RFC 4180 標準。
Q: 重複資料如何處理?
A: 資料表設定 UNIQUE KEY,使用 INSERT ... ON DUPLICATE KEY UPDATE 更新現有記錄,或匯入前先檢查。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved