You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CodeIgniter3导入Excel到MySQL时如何检测跳过重复数据并提示

CodeIgniter3 Excel导入重复数据拦截实现方案

实现逻辑分三层:数据库唯一约束兜底、Excel内数据去重、与库内已有数据去重,同时收集重复条目信息做前端提示,重复数据自动跳过不入库。


1. 前置配置:添加数据库唯一索引

首先在MySQL的user表上,根据你的重复判定规则添加唯一索引,这是避免脏数据的核心保障,以常用的email作为唯一判定字段为例,执行以下SQL:

-- 单字段唯一:email重复即判定为重复数据
ALTER TABLE `user` ADD UNIQUE INDEX `uk_email` (`email`);

-- 如果是多字段联合判定重复(例如姓名+手机号同时重复才算重复),可执行对应联合索引语句
-- ALTER TABLE `user` ADD UNIQUE INDEX `uk_name_mobile` (`name`, `mobile`);

2. 改造控制器导入逻辑

原逻辑未做任何去重判断直接批量入库,改造后增加两层去重、重复信息收集、提示信息暂存能力,替换后的控制器代码如下:

public function import_excel(){
    // 加载session库用于跨跳转存提示,若已经在autoload中配置可省略
    $this->load->library('session');
    if(isset($_FILES["fileExcel"]["name"])){
        $path=$_FILES["fileExcel"]["tmp_name"];
        $object=PHPExcel_IOFactory::load($path);
        foreach($object->getWorksheetIterator() as $worksheet)
        {         
            $highestRow=$worksheet->getHighestRow();
            // 初始化待入库数组、重复记录数组、Excel内唯一字段暂存数组
            $temp_data = [];
            $duplicate_list = [];
            $excel_unique_keys = [];
            $unique_field = 'email'; // 这里改成你判定重复的唯一字段,和数据库索引对应

            for($row=2; $row<=$highestRow; $row++)
            {
                $password=$worksheet->getCellByColumnAndRow(4,$row)->getValue();
                $name=$worksheet->getCellByColumnAndRow(1, $row)->getValue();
                $company=$worksheet->getCellByColumnAndRow(3,$row)->getValue();
                $email=strtolower($worksheet->getCellByColumnAndRow(2, $row)->getValue());
                $mobile=$worksheet->getCellByColumnAndRow(5,$row)->getValue();
                $level=$worksheet->getCellByColumnAndRow(6,$row)->getValue();
                $active=$worksheet->getCellByColumnAndRow(7,$row)->getValue();

                $row_data = array(
                    'name'=>$name,
                    'company'=>$company,
                    'email'=>$email,
                    'password'=>password_hash($password,PASSWORD_DEFAULT),
                    'mobile'=>$mobile,
                    'level'=>$level,
                    'active'=>$active
                );

                // 第一层:判断Excel内部是否存在重复
                if(in_array($row_data[$unique_field], $excel_unique_keys)){
                    $duplicate_list[] = "第{$row}行数据:{$row_data[$unique_field]} 与Excel内其他条目重复,已跳过";
                    continue;
                }
                $excel_unique_keys[] = $row_data[$unique_field];
                $temp_data[] = $row_data;
            }

            // 第二层:判断与数据库已有数据是否重复
            if(!empty($temp_data)){
                // 批量查询库中已存在的唯一值
                $exist_records = $this->m_data->get_exist_keys($excel_unique_keys, $unique_field);
                $exist_keys = array_column($exist_records, $unique_field);
                $valid_data = [];
                foreach($temp_data as $item){
                    if(in_array($item[$unique_field], $exist_keys)){
                        $duplicate_list[] = "数据:{$item[$unique_field]} 已在系统中存在,已跳过";
                        continue;
                    }
                    $valid_data[] = $item;
                }

                // 有效数据入库
                $insert_count = 0;
                if(!empty($valid_data)){
                    $insert_count = $this->m_data->insert($valid_data);
                }

                // 组装提示信息存入session flashdata
                $msg = "本次导入成功{$insert_count}条数据";
                if(!empty($duplicate_list)){
                    $msg .= ",跳过".count($duplicate_list)."条重复数据:<br>".implode('<br>', $duplicate_list);
                }
                $this->session->set_flashdata('import_msg', $msg);
            }
            redirect('userlist');
        }     
    }
}

3. 改造模型层代码

新增查询已存在唯一键的方法,调整插入方法返回实际入库条数:

// 批量查询已存在的唯一字段记录
public function get_exist_keys($keys, $field = 'email'){
    return $this->db->select($field)
                    ->from('user')
                    ->where_in($field, $keys)
                    ->get()
                    ->result_array();
}

// 批量插入有效数据,返回插入行数
public function insert($temp_data){
    $this->db->insert_batch('user',$temp_data);
    return $this->db->affected_rows();
}

4. 列表页展示导入提示

在userlist对应的控制器方法中,把session存储的提示信息传递给视图,在视图对应位置输出即可:

// userlist方法中取提示
$data['import_msg'] = $this->session->flashdata('import_msg');
$this->load->view('user_list', $data);

视图中对应位置输出提示:

<?php if(!empty($import_msg)):?>
<div class="alert alert-info">
    <?php echo $import_msg;?>
</div>
<?php endif;?>

注意事项

  • 数据库唯一索引必须添加,仅靠PHP代码去重无法应对并发场景下的脏数据写入
  • 如果单批次导入Excel行数超过1万条,建议拆分查询库内已有key的逻辑,分批查询避免PHP内存溢出
  • 可根据业务需求调整重复判定字段,只需要修改代码中$unique_field的取值、对应创建匹配的唯一索引即可

内容的提问来源于stack exchange,提问作者dhoeng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 17:01:18