將具有多表關聯的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即可;
