我正在尝试将一个包含大约 23.000 行的大型 CSV 文件导入到我的 MySQL 数据库中。我无法一次导入所有规则,那是行不通的。所以我想知道或者是否可以分块读取文件,即使我正在使用 cakePHP 事务。这是我到目前为止的代码:
// Get data source for transactions
$dataSource = $this->FeedImport->Product->getDataSource();
try{
//Start Transactions
$dataSource->begin();
// Create an empty array for the CSV data
$data = array();
$i = 0;
// read each data row in the file
while (($row = fgetcsv($handle)) !== false) {
// for each header field
foreach ($header as $k=>$head) {
// Remove any special characters from $head
$head = preg_replace('/[^A-Za-z0-9\-]/', '', $head);
if(array_key_exists($head, $this->fields)){
//Check the row contains an image, if so, download
if(preg_match('/\.(?:jpe?g|png|gif)$/i', $row[$k])){
foreach($this->fields[$head] as $table => $field){
$imageFileName = uniqid($supplier.'_');
$data[$i][$table][][$field] = $imageFileName.'.'.end(explode('.', $row[$k]));
$this->__importImg($row[$k]);
}
}else{
foreach($this->fields[$head] as $table => $field){
if($table == 'Term'){
if(isset($row[$k]) && !$this->FeedImport->Product->Term->find('first', array('conditions' => array('Term.name' => $row[$k])))){
if(!$this->FeedImport->Product->Term->save(
array(
'name' => $row[$k]
)
));
}
if(isset($row[$k])) $term = $this->FeedImport->Product->Term->find('first', array('conditions' => array('Term.name' => $row[$k])));
$data[$i][$table][$table][$field] = (isset($term['Term']['term_id'])) ? $term['Term']['term_id'] : '';
}else{
$data[$i][$table][$field] = (isset($row[$k])) ? $row[$k] : '';
}
}
}
}
}
$data[$i]['Product']['product_id_supplier'] = $data[$i]['Product']['slug'];
$data[$i]['Product']['supplier_id'] = $supplier;
$data[$i]['Product']['feedimport_id'] = 1;
$i++;
}
// save the row
if (!$this->FeedImport->Product->saveAll($data)) {
throw new Exception();
}
} catch(Exception $e) {
$dataSource->rollback($e);
}
$dataSource->commit();
我已将上面的代码放在一个单独的函数中,这样我就可以为 while 循环提供起始行和结束行。但是我遇到了困难,我不知道如何使用 fgetcsv 设置开始和结束规则。有人可以帮我吗?
我尝试过使用 fseek 等,但我就是无法完成它......有人可以帮助我吗?
我考虑过使用 LOAD DATA INFILE 来导入那些大的产品源,但我认为这不会很好地工作,因为我使用多个连接表和一些异常(exception)来将数据导入到多个表中..所以这太糟糕了.
最佳答案
可能的解决方法如下
while (($row = fgetcsv($handle)) !== false) {
if ($i === 5000){
try {
if (!$this->FeedImport->Product->saveAll($data))
throw new Exception();
} catch (Exception $e){
$dataSource->rollback($e);
}
$i = 0;
$data = [];
}
// Code
}
对于每 5000 条记录,它将提交数据,重置计数器和数据数组并继续。
关于php - 使用 CakePHP 批量导入 CSV 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20240066/