PHP Laravel:如何在将 xl/csv 导入 mysql 时避免重复数据?
Posted
技术标签:
【中文标题】PHP Laravel:如何在将 xl/csv 导入 mysql 时避免重复数据?【英文标题】:PHP Laravel : How to Avoid duplicate data while importing xl/ csv into mysql? 【发布时间】:2016-08-10 05:16:04 【问题描述】:我想将 csv 文件导入数据库,其中名称应始终唯一意味着如果发现任何重复的标题,则应避开该行并转到下一行。 如何使用 Laravel Controller 实现?
这是我使用的导入 csv/xl 的控制器:
public function importExcel()
if(Input::hasFile('import_file'))
$path = Input::file('import_file')->getRealPath();
$data = Excel::load($path, function($reader)
)->get();
if(!empty($data) && $data->count())
foreach ($data as $key => $value)
$insert[] = ['title' => $value->title, 'description' => $value->description];
if(!empty($insert))
DB::table('items')->insert($insert);
// dd('Insert Record successfully.');
return back();
【问题讨论】:
为什么要让它变得复杂? mysql 内置了处理 CSV 的工具 - 在文件中加载数据 我不清楚你的答案,请你详细说明一下? 阅读 mysql 的 LOAD DATA INFILE。关键是使用正确的工具完成工作 【参考方案1】:对 Matt Borja 的 answer 进行了一些改进。这也将检查表中较早的数据。
public function importExcel()
// Get current data from items table
$titles = Item::lists('title')->toArray();
if(Input::hasFile('import_file'))
$path = Input::file('import_file')->getRealPath();
$data = Excel::load($path, function($reader)
)->get();
if(!empty($data) && $data->count())
$insert = array();
foreach ($data as $key => $value)
// Skip title previously added using in_array
if (in_array($value->title, $titles))
continue;
$insert[] = ['title' => $value->title, 'description' => $value->description];
// Add new title to array
$titles[] = $value->title;
if(!empty($insert))
DB::table('items')->insert($insert);
// dd('Insert Record successfully.');
return back();
【讨论】:
我已更改为您的代码,但出现以下错误:FatalThrowableError in ItemController.php line 89: Cannot access protected property Maatwebsite\Excel\Collections\RowCollection::$title
It's in the line if (in_array($value->title, $titles))
该错误是针对 $value->title
部分的,它实际上在您的原始代码中。这适用于您的代码,它无法从 excel 文件中访问标题值。
在本地检查了代码,它工作正常。没有收到类似的错误。【参考方案2】:
在将数据插入数据库之前,您可以对数组变量 $insert[] 应用 array_unique() 函数。它会返回给你唯一的数组。
或者使表中的列唯一,使其不能接受重复值。
【讨论】:
如果我将列键设置为唯一,我会在导入数据时看到唯一键约束错误,而我使用 array() 唯一但它显示数组到字符串转换错误!【参考方案3】:我通常维护以前添加的项目的索引,如果我已经为它编制了索引,则跳过当前的迭代(重新添加)。
在您的示例中,大致如下:
public function importExcel()
// Index titles
$titles = [];
if(Input::hasFile('import_file'))
$path = Input::file('import_file')->getRealPath();
$data = Excel::load($path, function($reader)
)->get();
if(!empty($data) && $data->count())
foreach ($data as $key => $value)
// Skip title previously added using array_key_exists or in_array
if (array_key_exists($value->title, $titles))
continue;
$insert[] = ['title' => $value->title, 'description' => $value->description];
// Index added title
$titles[$value->title] = true; // or array_push
if(!empty($insert))
DB::table('items')->insert($insert);
// dd('Insert Record successfully.');
return back();
【讨论】:
我已将其更改为您的代码,但它仍然在数据库中保留重复值! 好吧,如果它们以前是导入的,它并不意味着要清理它。此时我会进行一些“打印”调试以验证$insert[]
数组不包含任何重复的标题。我还将在此方法开头的某处将 $insert
初始化为一个空数组,以确保它不会拾取任何全局变量等。不过,如果您要清理以前导入的重复记录,一个好的开始可能审核这些记录:SELECT title, COUNT(*) AS total FROM items GROUP BY title ORDER BY total DESC
以上是关于PHP Laravel:如何在将 xl/csv 导入 mysql 时避免重复数据?的主要内容,如果未能解决你的问题,请参考以下文章
作曲家和 laravel 7 不适用于 php 8.1 [关闭]
我在将 klaviyo 与 laravel 集成时遇到了这个错误