PHP MySQL多列转多行及CSV导出格式调整技术问询
如何用PHP While循环转换MySQL导出的CSV格式?
刚好我之前处理过类似的需求,给你一步步拆解怎么实现,不管是直接从MySQL拉数据处理,还是已经有了原始CSV文件,都能搞定,几千条数据完全不在话下。
方案一:直接从MySQL数据库读取并转换
如果你的数据还在MySQL里,直接查询处理是最方便的,咱们用mysqli来写示例(你也可以用PDO,逻辑是一样的):
1. 先建立数据库连接
// 替换成你的数据库信息 $host = 'localhost'; $user = '你的用户名'; $pass = '你的密码'; $dbname = '你的数据库名'; // 创建连接 $conn = new mysqli($host, $user, $pass, $dbname); // 检查连接是否成功 if ($conn->connect_error) { die("连接失败: " . $conn->connect_error); }
2. 查询数据表中的数据
// 替换成你的表名 $sql = "SELECT NAME, PHONE, EMAIL1, EMAIL2, EMAIL3 FROM 你的数据表名"; $result = $conn->query($sql);
3. 核心:用While循环处理每一行数据
这一步是关键,我们要把每一行里的三个邮箱拆分成单独的记录,还要处理CSV的格式问题:
// 先准备CSV的表头 $output = "NAME,PHONE,EMAIL\n"; // 用While循环遍历每一条数据库记录 while ($row = $result->fetch_assoc()) { // 提取当前行的姓名和电话 $name = $row['NAME']; $phone = $row['PHONE']; // 把三个邮箱放到数组里,方便后续循环处理 $emails = [ $row['EMAIL1'], $row['EMAIL2'], $row['EMAIL3'] ]; // 遍历每个邮箱,生成单独的记录 foreach ($emails as $email) { // 跳过空邮箱,避免生成无效记录(如果不需要跳过可以删掉这行判断) if (!empty(trim($email))) { // 转义字段里的特殊字符(比如逗号、双引号),符合CSV规范 $escapedName = '"' . str_replace('"', '""', $name) . '"'; $escapedPhone = '"' . str_replace('"', '""', $phone) . '"'; $escapedEmail = '"' . str_replace('"', '""', $email) . '"'; // 把拼接好的一行加到输出内容里 $output .= "$escapedName,$escapedPhone,$escapedEmail\n"; } } }
4. 输出或保存转换后的CSV
你可以直接让浏览器下载这个CSV,或者保存到服务器上:
// 方式1:直接让用户下载CSV header('Content-Type: text/csv'); header('Content-Disposition: attachment; filename="转换后的邮箱数据.csv"'); echo $output; // 方式2:保存到服务器文件(注释掉上面的header和echo,用下面这行) // file_put_contents('转换后的邮箱数据.csv', $output); // 最后别忘了关闭数据库连接 $conn->close();
方案二:处理已有的原始CSV文件
如果你已经导出了原始CSV,不想再查数据库,也可以直接读取文件处理,用PHP的fgetcsv和fputcsv会更省心,它们会自动处理CSV的特殊字符:
// 打开原始CSV文件(替换成你的文件路径) $inputFile = fopen('原始数据.csv', 'r'); // 创建并打开输出文件 $outputFile = fopen('转换后的数据.csv', 'w'); // 先写入新的表头 fputcsv($outputFile, ['NAME', 'PHONE', 'EMAIL']); // 跳过原始文件的表头(如果原始CSV有表头的话,没有就删掉这行) fgetcsv($inputFile); // 用While循环逐行读取原始CSV while (($row = fgetcsv($inputFile)) !== false) { $name = $row[0]; $phone = $row[1]; $emails = [$row[2], $row[3], $row[4]]; // 遍历邮箱生成新记录 foreach ($emails as $email) { if (!empty(trim($email))) { fputcsv($outputFile, [$name, $phone, $email]); } } } // 关闭文件 fclose($inputFile); fclose($outputFile);
几个关键注意点
- 处理特殊字符:不管是哪种方案,都要注意CSV里的逗号、双引号这些特殊字符,不然会导致CSV格式错乱,上面的代码已经帮你处理了。
- 跳过空邮箱:如果有的记录里某个邮箱字段是空的,跳过它就不会生成无效记录,如果你需要保留空邮箱的话,删掉
if (!empty(trim($email)))这行就行。 - 性能问题:这两种写法都是逐行处理,不会把所有数据都加载到内存里,所以几千条数据完全没问题,不会出现内存溢出的情况。
内容的提问来源于stack exchange,提问作者John C.
相关产品推荐
相关产品推荐

