如題,最近做的一個項目,需求就是這樣,寫個功能模塊,實現批量導入,為客服省點時間(好吧,需求就是需求)。好在插入的數據,都是些連續的數字,所以可以利用
foreach循環出這些數據,然后拼接成mysql的insert語句,進行大字段的批量插入。原理就是這么個原理,當然過程中有坑,什么打開擴展限制,暫且只看邏輯方面的吧。
框架的話,不是laravel,用的ci,實例代碼如下:
/**
* @desc 批量導入百萬條數據入庫(方法已經寫通用,數據最少5000條,最大100W條)
* @date 2017-10-26 20:45:45
* @param [int $start_no 起始號;int $end_no 截止號;string $express_type 類型]
* @author 1245049149@qq.com
* @return [type]
*/
public function import_million_express_no () {
//基本數據設置
header('Content-Type:text/html;charset=utf-8');
ini_set('memory_limit', '128M');
//設置類型對應數據庫中的表名
$express_to_form = [
'test1' => 'from1', //平台1對應的表名
'test2' => 'from2', //平台2對應的表名
];
//獲取參數
$start_no = trim($this->input->post('start_no'));
$end_no = trim($this->input->post('end_no'));
$express_type = trim($this->input->post('express_type'));
//判斷參數是否存在
if(!$start_no || !$end_no){
echo '<script>alert("錄入失敗,起始號和截止號不能為空為0");history.back();</script>';
return;
}
//起始單號不能大於等於截止單號,錄入數量至少為5000個
if ($start_no >= $end_no) {
echo '<script>alert("起始號不能,大於等於截止號!");history.back();</script>';
return;
} else {
if ($end_no - $start_no < 5000) {
echo '<script>alert("每次錄入號不能小於5000個!");history.back();</script>';
return;
}
if ($end_no - $start_no > 1000000) {
echo '<script>alert("每次錄入號不能大於1000000個!");history.back();</script>';
return;
}
}
//判斷數據類型是否存在
$table_name = $express_to_form[$express_type];
if(!$table_name){
echo '<script>alert("快遞類型有誤,無法進行打印!");history.back();</script>';
return;
}else{
//判斷初始單號,截止單號是否已經錄入
$sql1 = "select id from {$table_name} where express_no = {$start_no}";
$res1 = $this->db->query($sql1)->row();
if($res1){
echo '<script>alert("起始號已存在!");history.back();</script>';
return;
}
$sql2 = "select id from {$table_name} where express_no = {$end_no}";
$res2 = $this->db->query($sql2)->row();
if($res2){
echo '<script>alert("截止號已存在!");history.back();</script>';
return;
}
}
/***上面的一系列判斷的廢話可以不用看,直接看下面怎么對數據進行邏輯處理***/
//將起始號和截止號進行區間划分
$length = $end_no - $start_no + 1;
$times = floor($length / 5000);
$temp_data = [];
for($i=0;$i<$times;$i++){
$temp_data[$i]['start_no'] = $start_no; //起始編號
$temp_data[$i]['end_no'] = $start_no + 4999; //結束編號
$start_no += 5000; //下一輪循環的起始編號
}
//檢驗數組最后一組數據,判斷是否需要再添加
if($end_no > $temp_data[$times-1]['end_no']){
$temp_data[$times]['start_no'] = $temp_data[$times-1]['end_no'] + 1;
$temp_data[$times]['end_no'] = $end_no;
}
//進行導入數據庫sql語句的拼接
$add_time = time();
$add_user = $this->session->userdata['user_name'];
$tmp_val = "('{$add_time}','$add_user',0,'%s',0),";
for($j=0;$j<count($temp_data);$j++){
//循環拼接sql插入語句
$sql = "insert into {$table_name} (field1,field2,field3,field4,field5) values ";
for ($i=$temp_data[$j]['start_no']; $i<=$temp_data[$j]['end_no']; $i++) {
$sql .= sprintf($tmp_val, $i);
}
$sql = trim($sql, ',') . ';';
$bool = $this->db->query($sql);
//執行插入有誤,寫進日志異常表from3中
if(!$bool){
// 記錄日志
$log_info = array();
$log_info['field1'] = time();
$log_info['field2'] = '類型:'.$express_type.'執行有誤,單號'.$temp_data[$j]['start_no'].'-'.$temp_data[$j]['end_no'].'執行失敗';
$log_info['field3'] = $this->session->userdata['user_name'];
$this->db->insert('from3', $log_info);
//錯誤日志標志
$err_log_info = TRUE;
}
}
//數據返回
if($err_log_info){
echo '<script>alert("部分號執行失敗,請聯系管理員解決!");history.back();</script>';
}else{
echo '<script>alert("數據執行成功!!!");history.back();</script>';
}
return;
}
上面就是封裝的一個完整的類,參數驗證什么的,可以不用看了,直接看sql語句拼接,其實最后發現吧,做出來也沒啥。經過測試,基本耗時在10s左右徘徊,恩恩,暫時先這樣,有好的思路,歡迎交流。不說了,得繼續加班去了,233
