如何用PHP读取CSV/Excel指定单元格数据并导入MySQL数据库?
需求说明
现有一段PHP代码可将CSV文件的指定列数据导入MySQL的subject表,但目前仅支持按固定列索引导入。现在需要实现通过识别单元格表头内容,定位到目标字段对应的列后,导入该列下方的所有对应数据(比如先找到单元格内容为"SUBJ_CODE"的位置,再将该列下方数据匹配到数据库表的SUBJ_CODE字段)。
现有代码
<?php include 'db.php'; if(isset($_POST["Import"])){ echo $filename=$_FILES["file"]["tmp_name"]; if($_FILES["file"]["size"] > 0) { $file = fopen($filename, "r"); while (($emapData = fgetcsv($file, 10000, ",")) !== FALSE) { //It wiil insert a row to our subject table from our csv file` $sql = "INSERT into subject (`SUBJ_CODE`, `SUBJ_DESCRIPTION`, `UNIT`, `PRE_REQUISITE`,COURSE_ID, `AY`, `SEMESTER`) values('$emapData[1]','$emapData[2]','$emapData[3]','$emapData[4]','$emapData[5]','$emapData[6]','$emapData[7]')"; //we are using mysql_query function. it returns a resource on true else False on error $result = mysqli_query( $conn, $sql ); if(! $result ) { echo "<script type=\"text/javascript\"> alert(\"Invalid File:Please Upload CSV File.\"); window.location = \"index.php\" </script>"; } } fclose($file); //throws a message if data successfully imported to mysql database from excel file echo "<script type=\"text/javascript\"> alert(\"CSV File has been successfully Imported.\"); window.location = \"index.php\" </script>"; //close of connection mysqli_close($conn); } } ?>
实现思路
- 读取CSV第一行(表头行),建立表头文本与列索引的映射关系,记录每个目标数据库字段对应的列位置。
- 跳过表头行,从第二行开始读取数据,通过映射关系匹配对应字段的数据。
- 替换直接拼接SQL的写法,使用预处理语句防止SQL注入。
- 添加缺失表头检查、空行跳过等逻辑,提升导入稳定性。
修改后的代码(支持表头匹配导入)
<?php include 'db.php'; if(isset($_POST["Import"])){ $filename = $_FILES["file"]["tmp_name"]; if($_FILES["file"]["size"] > 0){ $file = fopen($filename, "r"); // 读取表头行,建立字段与列索引的映射 $header = fgetcsv($file, 10000, ","); $indexMap = []; // 定义数据库字段与Excel表头的对应关系(可根据实际表头调整) $dbFieldMap = [ 'SUBJ_CODE' => 'SUBJ_CODE', 'SUBJ_DESCRIPTION' => 'SUBJ_DESCRIPTION', 'UNIT' => 'UNIT', 'PRE_REQUISITE' => 'PRE_REQUISITE', 'COURSE_ID' => 'COURSE_ID', 'AY' => 'AY', 'SEMESTER' => 'SEMESTER' ]; // 遍历表头,记录每个字段对应的列索引 foreach($dbFieldMap as $dbField => $excelHeader){ $colIndex = array_search($excelHeader, $header); if($colIndex !== false){ $indexMap[$dbField] = $colIndex; } } // 检查是否缺少必要表头 $missingFields = array_diff(array_keys($dbFieldMap), array_keys($indexMap)); if(!empty($missingFields)){ echo "<script type=\"text/javascript\"> alert(\"Excel文件缺少必要表头:" . implode(',', $missingFields) . "\"); window.location = \"index.php\" </script>"; fclose($file); mysqli_close($conn); exit; } // 预处理SQL,防止注入 $sql = "INSERT into subject (`SUBJ_CODE`, `SUBJ_DESCRIPTION`, `UNIT`, `PRE_REQUISITE`, `COURSE_ID`, `AY`, `SEMESTER`) values(?, ?, ?, ?, ?, ?, ?)"; $stmt = mysqli_prepare($conn, $sql); // 读取数据行并插入数据库 while (($emapData = fgetcsv($file, 10000, ",")) !== FALSE){ // 跳过空行 if(empty(array_filter($emapData))){ continue; } // 通过映射获取对应列的数据 $subjCode = $emapData[$indexMap['SUBJ_CODE']] ?? ''; $subjDesc = $emapData[$indexMap['SUBJ_DESCRIPTION']] ?? ''; $unit = $emapData[$indexMap['UNIT']] ?? ''; $preReq = $emapData[$indexMap['PRE_REQUISITE']] ?? ''; $courseId = $emapData[$indexMap['COURSE_ID']] ?? ''; $ay = $emapData[$indexMap['AY']] ?? ''; $semester = $emapData[$indexMap['SEMESTER']] ?? ''; // 绑定参数并执行插入 mysqli_stmt_bind_param($stmt, "sssssss", $subjCode, $subjDesc, $unit, $preReq, $courseId, $ay, $semester); $result = mysqli_stmt_execute($stmt); if(!$result){ echo "<script type=\"text/javascript\"> alert(\"导入失败:" . mysqli_error($conn) . "\"); window.location = \"index.php\" </script>"; fclose($file); mysqli_stmt_close($stmt); mysqli_close($conn); exit; } } fclose($file); mysqli_stmt_close($stmt); mysqli_close($conn); echo "<script type=\"text/javascript\"> alert(\"CSV文件已成功导入。\"); window.location = \"index.php\" </script>"; } } ?>
补充说明
- 如果需要支持.xls/.xlsx格式的Excel文件,建议使用
PhpSpreadsheet库,它可以直接读取Excel单元格内容,处理逻辑与CSV一致:先读取表头建立映射,再读取数据行匹配导入。 - 代码中添加了错误捕获、空行过滤等逻辑,避免因文件格式问题导致导入失败。
内容的提问来源于stack exchange,提问作者Jeiro
相关产品推荐
相关产品推荐

