項目總結04:SQL批量導入數據:將具有多表關聯的Excel數據,通過sql語句腳本的形式,導入到數據庫


 將具有多表關聯的Excel數據,通過sql語句腳本的形式,導入到數據庫

寫在前面:本文用的語言是java;數據庫是MySql;

需求:在實際項目中,經常會被客戶要求,做批量導入數據;一般的簡單的單表數據,可以直接通過Navicat的導入功能,將Excel表格信息直接導入;單實際情況是——需要導入的數據要分別保存在對應的多張表中,其中一張主表,多張關聯副表,這個時候再用Navicat的導入功能,無法滿足需求! 本文總結一種方法處理這種批量錄入多表數據;如下。

核心思路:將Excel數據表中的數據,保存到TXT中;通過腳本讀取TXT中的數據,寫成對應的sql語句;在Navicat運行sql語句,實現保存目的;

為了展示完整的操作步驟,我准備了一個簡單的業務需求:保存學生基本信息和學生選課信息;原始EXCEL數據在一張表里;需要將數據分別保存在student_info和select_class兩張數據表中

具體操作步驟:

1.准備Excel原始數據:Excel原始數據有一定的格式要求,要求每列信息必須明確(1表示選課0表示沒選),如下圖:

將Excel數據復制到TXT中,如下;

2.准備初始化數據表;

CREATE TABLE `student_info` (
  `student_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '學生id',
  `name` varchar(10) DEFAULT NULL,
  `sex` varchar(1) DEFAULT NULL,
  `age` int(2) DEFAULT NULL,
  PRIMARY KEY (`student_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `select_class` (
  `id` int(10) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `student_id` int(10) DEFAULT NULL COMMENT '學生id',
  `class_name` varchar(10) DEFAULT NULL COMMENT '課程名稱',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

初始化的數據表數據表,如下:

 

3.編寫腳本(核心步驟),代碼如下: 

package com.fh.readfile;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TestFileReadUtil {
	private static int Number = 0;
	/**
	 * 功能:Java讀取txt文件的內容 步驟:1:先獲得文件句柄 2:獲得文件句柄當做是輸入一個字節碼流,需要對這個輸入流進行讀取
	 * 3:讀取到輸入流后,需要讀取生成字節流 4:一行一行的輸出。readline()。 備注:需要考慮的是異常情況
	 * @param filePath
	 *            文件路徑[到達文件:如: D:\aa.txt]
	 * @return 將這個文件按照每一行切割成數組存放到list中。
	 */
	public static List<String> readTxtFileIntoStringArrList(String filePath) {
		List<String> list = new ArrayList<String>();
		try {
			File file = new File(filePath);
			if (file.isFile() && file.exists()) { // 判斷文件是否存在
				InputStreamReader read = new InputStreamReader(new FileInputStream(file));// 考慮到編碼格式
				BufferedReader bufferedReader = new BufferedReader(read);
				String lineTxt = null;
				while ((lineTxt = bufferedReader.readLine()) != null) {
					list.add(lineTxt);
				}
				bufferedReader.close();
				read.close();
			} else {
				System.out.println("找不到指定的文件");
			}
		} catch (Exception e) {
			System.out.println("讀取文件內容出錯");
			e.printStackTrace();
		}
		return list;
	}
	//學生基本信息sql語句模板
	private static String studentMainInfoSql = "insert into student_info(student_id,name,sex,age)value(${student_id},'${name}','${sex}',${age});";//注意'${name}'需要單引號,表示是字符串,否則生成的sql語句會出錯
	//學生選課信息sql語句模板
	private static String selectClassInfoSql= "insert into select_class(id,student_id,class_name) value(${id},${student_id},'${class_name}');";
	//Excel數據表頭 
	private static final String[] HEAD_ARRAY = new String[]{"Name","Sex","Age","Chinese","Math","English","Science"};
	//根據表頭名稱獲取列索引索引"Name","Sex","Age","Chinese","Math","English","Science"分別是0 1 2 3 4 5 6
	private static int getIndex(String headName){
		for(int i=0;i<HEAD_ARRAY.length;i++){
			String head = HEAD_ARRAY[i];
			if(head.equals(headName)){
				return i;
			}
		}
		return -1;
	}
	//生成學生基本信息sql語句方法
	private static void createStudentInfo(List<String>lineList){
		int  student_id =Number;//定義student_id的起始值
		for(String line:lineList){//遍歷每一行數據
			student_id++;
			String[] array = line.split("\t");//將每一行數據根據空格拆分成數組
			//將sql模板中的value值是用真實數據替換(使用replace()方法)
			String studentInfoSql = studentMainInfoSql.replace("${student_id}", student_id+"").
					replace("${name}", array[getIndex("Name")]).
					replace("${sex}", array[getIndex("Sex")]).
					replace("${age}", array[getIndex("Age")]);	
			//打印sql語句
			System.out.println(studentInfoSql);
		}
	}
	//生成學生選課信息sql語句
	private static void createSelectClassInfo(List<String>lineList){
		int  student_id =Number;//定義student_id的起始值
		int  select_class_id =Number;//定義select_class_id的起始值
		int startIndex = getIndex("Chinese");//獲取選課信息列的首列索引
		int endIndex = getIndex("Science");//獲取選課信息列的末列索引
		for(String line:lineList){//遍歷每一行數據
			student_id++;
			String[] array = line.split("\t");//將每一行數據根據空格拆分成數組
			for(int i=startIndex;i< (endIndex+1);i++){//遍歷每一行數據中每個課程的選擇情況
				if(array[i].equals("1")){//如果是1,表示選擇該課程,要生成對應的sql語句
					select_class_id++;
					String className =HEAD_ARRAY[i];	
					//生成學生選課信息sql語句
					String selectClassSql = selectClassInfoSql.replace("${id}", select_class_id+"").
							replace("${student_id}", student_id+"").
							replace("${class_name}", className);
					//打印 語句
					System.out.println(selectClassSql);
				}
			}
		}	
	}	
	//main方法,打印最終sql語句
	public static void main(String[] args) {	
		//讀取txt文件中的數據,格式是list集合
		List<String> lineList = readTxtFileIntoStringArrList("txt/student.txt");
		//去掉第一行數據,因為第一行數據是表頭
		lineList.remove(0);
		//打印學生基本信息sql語句
		createStudentInfo(lineList);
		//打印學生選課數據sql語句
		createSelectClassInfo(lineList);

	}
}

4.運行腳本,得到sql語句;如下:

insert into student_info(student_id,name,sex,age)value(1,'林俊傑','男',30);
insert into student_info(student_id,name,sex,age)value(2,'趙麗穎','女',28);
insert into student_info(student_id,name,sex,age)value(3,'胡歌','男',36);
insert into select_class(id,student_id,class_name) value(1,1,'Chinese');
insert into select_class(id,student_id,class_name) value(2,1,'Science');
insert into select_class(id,student_id,class_name) value(3,2,'Chinese');
insert into select_class(id,student_id,class_name) value(4,2,'Math');
insert into select_class(id,student_id,class_name) value(5,3,'English');
insert into select_class(id,student_id,class_name) value(6,3,'Science');

在navicat中運行sql語句,最終結果,如下;

 5.總結:本案例是多表數據導入案例中最簡單的一張,但是基本思路已經表達完整;再多的關聯表,沿用select_class即可;

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM