
在web应用开发中,从csv文件导入数据到数据库是常见的需求。csv(comma separated values)文件以纯文本形式存储表格数据,每行记录由逗号或其他特定字符分隔。本教程将以一个包含两列数据的csv文件为例,演示如何将其导入到mysql数据库的users表中。
示例CSV数据格式:
BGYR002217;FK-066 BGYR002218;FK-140
注意,此示例中数据字段的分隔符是分号(;),而非默认的逗号(,)。
首先,我们需要在MySQL数据库中创建一个用于存储CSV数据的表。假设表名为users,包含szam和forras_szam两列。
CREATE TABLE `users` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`szam` VARCHAR(255) NOT NULL,
`forras_szam` VARCHAR(255) NOT NULL
);为了导入CSV文件,通常需要一个HTML表单供用户上传文件,然后PHP脚本接收并处理该文件。
立即学习“PHP免费学习笔记(深入)”;
创建一个简单的HTML文件(例如 index.html)来提供文件上传功能:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>CSV文件导入</title>
</head>
<body>
<h1>上传CSV文件到MySQL</h1>
<form action="import.php" method="post" enctype="multipart/form-data">
<label for="upcsv">选择CSV文件:</label>
<input type="file" name="upcsv" id="upcsv" accept=".csv">
<button type="submit">上传并导入</button>
</form>
</body>
</html>这是核心的PHP脚本,负责数据库连接、CSV文件读取、解析和数据插入。
<?php
// 1. 数据库配置
$dbHost = 'localhost';
$dbName = 'test'; // 替换为你的数据库名
$dbChar = 'utf8mb4'; // 推荐使用 utf8mb4 以支持更广泛的字符集
$dbUser = 'root'; // 替换为你的数据库用户名
$dbPass = ''; // 替换为你的数据库密码
// 2. 建立PDO数据库连接
try {
$pdo = new PDO(
"mysql:host=" . $dbHost . ";dbname=" . $dbName . ";charset=" . $dbChar,
$dbUser,
$dbPass,
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // 错误报告模式:抛出异常
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // 默认获取模式:关联数组
PDO::ATTR_EMULATE_PREPARES => false // 禁用模拟预处理,使用原生预处理
]
);
} catch (PDOException $ex) {
exit("数据库连接失败: " . $ex->getMessage());
}
// 3. 检查文件上传
if (!isset($_FILES["upcsv"]) || $_FILES["upcsv"]["error"] !== UPLOAD_ERR_OK) {
exit("文件上传失败或未选择文件。错误码: " . ($_FILES["upcsv"]["error"] ?? 'N/A'));
}
$tmpFilePath = $_FILES["upcsv"]["tmp_name"];
if (!is_uploaded_file($tmpFilePath)) {
exit("无效的文件上传。");
}
// 4. 打开并读取CSV文件
// 注意:fgetcsv 默认分隔符是逗号(,), 如果CSV文件使用分号(;)作为分隔符,需要明确指定
$fh = fopen($tmpFilePath, "r");
if ($fh === false) {
exit("无法打开上传的CSV文件。");
}
// 准备SQL插入语句,使用正确的PDO占位符 `?`
// 错误示例:VALUES (?;?)
// 正确示例:VALUES (?,?)
$stmt = $pdo->prepare("INSERT INTO users (szam, forras_szam) VALUES (?, ?)");
$importedRows = 0;
while (($row = fgetcsv($fh, 0, ';')) !== false) { // 明确指定分号作为分隔符
// 检查行数据是否有效,防止空行或格式不符的行导致错误
if (count($row) < 2) {
echo "跳过无效行: " . implode(';', $row) . "<br>";
continue;
}
try {
// 执行预处理语句,绑定CSV行数据到占位符
$stmt->execute([$row[0], $row[1]]);
$importedRows++;
} catch (PDOException $ex) {
// 捕获并输出每行导入的错误信息,而不是中断整个过程
echo "导入行错误: " . implode(';', $row) . " - " . $ex->getMessage() . "<br>";
}
}
// 5. 关闭文件句柄
fclose($fh);
echo "导入完成!成功导入 " . $importedRows . " 行数据。";
?>原始问题中出现的错误 SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax;... VALUES (?;?) 明确指出SQL语法错误。
问题根源: PDO预处理语句中,参数占位符只能是问号(?)或具名参数(例如:param_name)。将分号(;)用作占位符是错误的语法。分号在SQL中通常用作语句的终止符,而不是参数绑定符号。
解决方案: 将SQL语句中的 VALUES (?;?) 改为 VALUES (?,?)。
// 错误示例:
// $stmt = $pdo->prepare("INSERT INTO users (szam, forras_szam) VALUES (?;?)");
// 正确示例:
$stmt = $pdo->prepare("INSERT INTO users (szam, forras_szam) VALUES (?, ?)");原始CSV数据 BGYR002217;FK-066 使用分号作为字段分隔符。fgetcsv函数默认使用逗号(,)作为分隔符。如果CSV文件使用其他字符作为分隔符,必须在fgetcsv函数的第三个参数中明确指定。
问题根源: 如果未指定分隔符,fgetcsv会将 BGYR002217;FK-066 视为单个字段读取到 $row[0] 中,导致 $row[1] 未定义,从而引发 Undefined array key 1 警告,并最终导致 execute 方法参数不足或不正确。
解决方案: 在调用 fgetcsv 时,将分隔符参数设置为分号(;):
// 错误示例(如果CSV使用分号分隔):
// while (($row = fgetcsv($fh)) !== false) { ... }
// 正确示例:
while (($row = fgetcsv($fh, 0, ';')) !== false) { // 0表示最大行长度不限制,';'是分隔符
// ...
}在实际应用中,对文件操作和数据库操作进行适当的错误处理至关重要。
通过本教程,我们学习了如何使用PHP和PDO将CSV文件导入MySQL数据库。核心要点包括:正确使用PDO预处理语句的占位符(?),以及根据CSV文件的实际分隔符配置fgetcsv函数。同时,强调了错误处理、健壮性设计和性能优化在数据导入过程中的重要性。遵循这些指导原则,将能够构建出高效、安全且稳定的CSV数据导入功能。
以上就是使用PHP和PDO将CSV文件导入MySQL数据库的教程的详细内容,更多请关注php中文网其它相关文章!
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号