使用 PHP/MySQL 导入 CSV 数据
Posted
技术标签:
【中文标题】使用 PHP/MySQL 导入 CSV 数据【英文标题】:Importing CSV data using PHP/MySQL 【发布时间】:2012-07-11 23:52:54 【问题描述】:我在尝试从 CSV 导入数据时遇到了一些问题,并且有几个问题我自己还没有解决。
首先,这是我的代码,可以帮助您正确看待事物(稍微整理一下,删除 CSS 和 DB 连接):
<body>
<div id="container">
<div id="form">
<?php
$deleterecords = "TRUNCATE TABLE tablename"; //empty the table of its current records
mysql_query($deleterecords);
//Upload File
if (isset($_POST['submit']))
if (is_uploaded_file($_FILES['filename']['tmp_name']))
echo "<h1>" . "File ". $_FILES['filename']['name'] ." uploaded
successfully." . "</h1>";
echo "<h2>Displaying contents:</h2>";
readfile($_FILES['filename']['tmp_name']);
//Import uploaded file to Database
$handle = fopen($_FILES['filename']['tmp_name'], "r");
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE)
$import="INSERT into importing(text,number)values('$data[0]','$data[1]')";
mysql_query($import) or die(mysql_error());
fclose($handle);
print "Import done";
//view upload form
else
print "Upload new csv by browsing to file and clicking on Upload<br />\n";
print "<form enctype='multipart/form-data' action='upload.php' method='post'>";
print "File name to import:<br />\n";
print "<input size='50' type='file' name='filename'><br />\n";
print "<input type='submit' name='submit' value='Upload'></form>";
?>
</div>
</div>
</body>
它基本上是对我在各种方法上多次尝试后找到的一个示例的改编。
我的 CSV 有两列数据,第一列是文本,第二列是整数 数据库中的表也有两列,第一列叫“文本”,第二列叫“数字”
所以我的问题是:
-
正在上传的文本在每个字段中都显示为 0,我不知道为什么
我一直在阅读有关以“”结尾的数据,如果发生这种情况,我将如何对其进行排序?
如何忽略标题等 CSV 的前 X 行?
在整个过程中数据格式是否发生了变化,还是可以在图表中使用?例如小数一旦放入数据库中会一直保持小数吗?
我认为这涵盖了所有内容,在此先感谢您的帮助!
编辑:
刚做了10000条记录上传测试,报错:
“致命错误:超过 30 秒的最大执行时间”
有什么想法吗?
【问题讨论】:
如果您要上传大文件,也请查看Load Data Infile,因为它更快。LOAD DATA INFILE '/tmp/test.txt' INTO TABLE test IGNORE 1 LINES;
@Fluffeh 我尝试使用该方法,但由于某种原因,当我将其合并到 PHP 中时它不起作用。速度肯定会很有用,因为它最终会是一个大文件。
检查我更新的答案。
@Pidge: LOAD DATA INFILE
在 PHP 中效果很好:我有它为我工作,几乎可以立即加载 300,000 行的 CSV 文件。它非常灵活,速度非常快,让任何基于 PHP 循环的解决方案都显得很傻。
@Pidge:csv 导入主要由 cron 完成,因此您可以使用任何方法。
【参考方案1】:
数据库连接:
try
$conn = mysqli_connect($servername, $username, $password, $db);
//echo "Connected successfully";
catch (exception $e)
echo "Connection failed: " . $e->getMessage();
读取CSV文件并上传到数据库表的代码。
$file = fopen($filename, "r");
while (($getData = fgetcsv($file, 10000, ",")) !== FALSE)
$sql = "INSERT into db_table
values ('','" . $getData[1] . "','" . $getData[2] . "','" . $getData[3] . "','" . $getData[4] . "','" . $getData[5] . "','" . $getData[6] . "')";
$result = mysqli_query($conn, $sql);
if (!isset($result))
echo "<script type=\"text/javascript\">
alert(\"Invalid File:Please Upload CSV File.
window.location = \"home.do\"
</script>";
else
echo "<script type=\"text/javascript\">
alert(\"CSV File has been successfully Imported.\");
window.location = \"home.do\"
</script>";
fclose($file);
【讨论】:
直接在php中编写java脚本只是为了重定向是非常糟糕的做法【参考方案2】:我认为解析 csv 时要记住的主要事情是它遵循一些简单的规则:
a)这是一个文本文件,很容易打开 b) 每行由行尾决定 \n 所以首先将字符串拆分为行 c) 每行/行都有由逗号确定的列,因此将每行拆分为一个列数组
have a read of this post 看看我在说什么
一旦你掌握了它并变得非常有用,它实际上很容易做到。
【讨论】:
【参考方案3】:前几天我回答了一个几乎相同的问题:Save CSV files into mysql database
MySQL 有一个功能LOAD DATA INFILE
,它允许它直接在单个 SQL 查询中导入 CSV 文件,根本不需要通过 PHP 程序在循环中处理它。
简单示例:
<?php
$query = <<<eof
LOAD DATA INFILE '$fileName'
INTO TABLE tableName
FIELDS TERMINATED BY '|' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
(field1,field2,field3,etc)
eof;
$db->query($query);
?>
就这么简单。
没有循环,没有大惊小怪。而且比在 PHP 中解析要快得多。
这里是 MySQL 手册页:http://dev.mysql.com/doc/refman/5.1/en/load-data.html
希望有帮助
【讨论】:
对不起,我在网上淘的时候都没遇到过,明显是我找错东西了!如果您能快速查看一下我把它放在哪里,我将永远感激好先生 :) (pastebin.com/e9wvsT4c)(再次到处保存垃圾邮件) 您的 pastebin 代码看起来好像您的想法是正确的。一些错误仍然存在(例如,$filename
未设置),但我相信你会很容易地解决这些问题。
如果遇到“在 MySQL 中加载数据 infile 的访问被拒绝”切换 LOAD DATA INFILE
到 LOAD DATA LOCAL INFILE
。来源:***.com/a/4162310/394969
这样安全吗?恶意用户可能会在文件中放入 sql 并破坏数据库?
这也假设数据库首先可以访问文件,如果数据库在隔离容器中运行,这可能不是那么简单。【参考方案4】:
set_time_limit(10000);
$con = mysql_connect('127.0.0.1','root','password');
if (!$con)
die('Could not connect: ' . mysql_error());
mysql_select_db("db", $con);
$fp = fopen("file.csv", "r");
while( !feof($fp) )
if( !$line = fgetcsv($fp, 1000, ';', '"'))
continue;
$importSQL = "INSERT INTO table_name VALUES('".$line[0]."','".$line[1]."','".$line[2]."')";
mysql_query($importSQL) or die(mysql_error());
fclose($fp);
mysql_close($con);
【讨论】:
@Pidge “刚刚完成了 10,000 条记录上传的测试并得到了错误..”使用这个脚本,我已经从 CSV 导入了超过 100 万条记录。它应该适合你。【参考方案5】:$i=0;
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE)
if($i>0)
$import="INSERT into importing(text,number)values('".$data[0]."','".$data[1]."')";
mysql_query($import) or die(mysql_error());
$i=1;
【讨论】:
解决了文本问题:) 出于好奇,这是什么部分使它忽略了 CSV 的第一行? 与您的代码的代码差异将得到您的答案。接受适当的答案作为已接受的答案【参考方案6】:letsay $infile = a.csv //需要导入文件。
class blah
static public function readJobsFromFile($file)
if (($handle = fopen($file, "r")) === FALSE)
echo "readJobsFromFile: Failed to open file [$file]\n";
die;
$header=true;
$index=0;
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE)
// ignore header
if ($header == true)
$header = false;
continue;
if ($data[0] == '' && $data[1] == '' ) //u have oly 2 fields
echo "readJobsFromFile: No more input entries\n";
break;
$a = trim($data[0]);
$b = trim($data[1]);
if (check_if_exists("SELECT count(*) FROM Db_table WHERE a='$a' AND b='$b'") === true)
$index++;
continue;
$sql = "INSERT INTO DB_table SET a='$a' , b='$b' ";
@mysql_query($sql) or die("readJobsFromFile: " . mysql_error());
$index++;
fclose($handle);
return $index; //no. of fields in database.
function
check_if_exists($sql)
$result = mysql_query($sql) or die("$sql --" . mysql_error());
if (!$result)
$message = 'check_if_exists::Invalid query: ' . mysql_error() . "\n";
$message .= 'Query: ' . $sql;
die($message);
$row = mysql_fetch_assoc ($result);
$count = $row['count(*)'];
if ($count > 0)
return true;
return false;
$infile=a.csv;
blah::readJobsFromFile($infile);
希望这会有所帮助。
【讨论】:
尽管我为我的用例重构了您的一些代码,但这是一个很好的起点。谢谢。以上是关于使用 PHP/MySQL 导入 CSV 数据的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 if else 条件在 php mysql 数据库中导入 csv 数据
使用 PHP/MySQL 导出大型 CSV 数据的最佳方法是啥?
如何使用 CSV(平面文件)更新 MySQL 数据库并在插入前验证数据