Excel生成建表語句


簡介

前言

最近公司開展新項目,由於項目進度緊急,部分項目負責人不在現在,建表相關的使用的是Excel,由於Excel拼接過於麻煩,博豬COPY了一下大神的代碼,修改了部分代碼,以便適用於我們項目。

參照博客地址:博客地址

准備工作

Excel模板

模板可以根據自己的習慣來創建,需要注意的是建表時我們需要的參數有:數據庫名,表名,表注釋,列名,列注釋,列類型,列長度,列精度,是否主鍵,是否非空。

image-20210224163802424

Database Name your database name Table Name (physical name) your table name Table Name (logical name) 你的表名
Column Name (physical name) Column Name (logical name) Type Length Decimal PK NOT NULL
column 1 列 1 VARCHAR 255 * *

擼代碼

依賴

首先新建maven項目,並導入poi(用於操作excel)、lombok(簡化實體類代碼)依賴:

<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi</artifactId>
	<version>3.15</version>
</dependency>
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi-ooxml</artifactId>
	<version>3.15</version>
</dependency>
<dependency>
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
	<version>1.18.16</version>
	<scope>provided</scope>
</dependency>

因為我們只需要控制台輸入,並且輸出sql語句,所以只需要這3個依賴即可。

相關實體類

數據類型常量類TableTypeConstant.java

定義MySQL的數據類型

public class TableTypeConstant {
	public static final String INT = "int";
	public static final String VARCHAR ="varchar";
	public static final String DATE = "date";
	public static final String DATE_TIME="datetime";
	public static final String TEXT ="text";
	public static final String LONG_TEXT = "longtext";
	public static final String CHAR = "char";
	public static final String LONG = "long";
	public static final String TIME_STAMP = "timestamp";
	public static final String DECIMAL="decimal";
}

字段信息ColumnEntity.java

定義我們關注的字段的關鍵信息

@Data
public class ColumnEntity {
	/*物理列名*/
	private String physicalColumnName;
	/*邏輯列名*/
	private String logicalColumnName;
	/*類型*/
	private String type;
	/*長度*/
	private String length;
	/*精度*/
	private String decimal;
	/*是否主鍵*/
	private boolean isPrimaryKey;
	/*是否非空*/
	private boolean isNotNull;
}

表信息TableEntity.java

定義建表語句需要的信息

@Data
public class TableEntity {
	/*列信息*/
	private List<ColumnEntity> entities;
	/*表物理名*/
	private String physicalTableName;
	/*表邏輯名*/
	private String logicalTableName;
	/*數據庫名*/
	private String databaseName;
}

業務類

生成SQL語句Excel.java

包含3個方法

  • TableEntity readExcel(String excelPath) 解析Excel並返回TableEntity
  • void convertSQL(TableEntity tableEntity) 根據TableEntity生成SQL語句並寫入txt
  • void writeTXT(String path, String value, String fileName) 將字符串寫入txt文件
import com.bossYang.myBatisTest.bean.ColumnEntity;
import com.bossYang.myBatisTest.bean.TableEntity;
import com.bossYang.myBatisTest.bean.TableTypeConstant;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;

public class Excel {

	/**
	 * 讀取excel並轉換為表實體
	 * 
	 * @param excelPath
	 * @return
	 */
	public TableEntity readExcel(String excelPath) {
		// 解析模板對象List
		List<ColumnEntity> entities = new ArrayList<ColumnEntity>();
		// 表物理名
		String physicalTableName = null;
		// 表邏輯名
		String logicalTableName = null;
		// 數據庫名
		String databaseName = null;
		try {
			// String encoding = "GBK";
			File excel = new File(excelPath);
			if (excel.isFile() && excel.exists()) { // 判斷文件是否存在

				String[] split = excel.getName().split("\\."); // .是特殊字符,需要轉義!!!!!
				Workbook wb;
				// 根據文件后綴(xls/xlsx)進行判斷
				if ("xls".equals(split[1])) {
					FileInputStream fis = new FileInputStream(excel); // 文件流對象
					wb = new HSSFWorkbook(fis);
				} else if ("xlsx".equals(split[1])) {
					wb = new XSSFWorkbook(excel);
				} else {
					System.out.println("文件類型錯誤!");
					return null;
				}

				// 開始解析
				Sheet sheet = wb.getSheetAt(0); // 讀取sheet 0

				int firstRowIndex = sheet.getFirstRowNum() + 2; // 第一、二行是列名,所以不讀,從第三行開始讀
				int lastRowIndex = sheet.getLastRowNum();
				// System.out.println("firstRowIndex: "+firstRowIndex);
				// System.out.println("lastRowIndex: "+lastRowIndex);

				// 解析模板對象List
				entities = new ArrayList<ColumnEntity>();
				// 數據庫名
				databaseName = sheet.getRow(0).getCell(1).getStringCellValue();
				// 表物理名
				physicalTableName = sheet.getRow(0).getCell(3).getStringCellValue();
				// 表邏輯名
				logicalTableName = sheet.getRow(0).getCell(5).getStringCellValue();

				for (int rIndex = firstRowIndex; rIndex <= lastRowIndex; rIndex++) { // 遍歷行
					// System.out.println("rIndex: " + rIndex);
					ColumnEntity entity = new ColumnEntity();
					Row row = sheet.getRow(rIndex);
					if (row != null) {
						if (row.getCell(0, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue() == null || row
								.getCell(0, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue().isEmpty()) {
							continue;
						}
						/*
						 * int firstCellIndex = row.getFirstCellNum(); int lastCellIndex =
						 * row.getLastCellNum(); for (int cIndex = firstCellIndex; cIndex <
						 * lastCellIndex; cIndex++) { //遍歷列 Cell cell = row.getCell(cIndex); if (cell !=
						 * null) { System.out.println(cell.toString()); } }
						 */
						
						// 解析對象
						entity.setPhysicalColumnName(
								row.getCell(0, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue());// 列物理名
						entity.setLogicalColumnName(
								row.getCell(1, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue());// 列邏輯名
						entity.setType(row.getCell(2, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue());// 類型
						entity.setLength(row.getCell(3, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue());// 長度
						entity.setDecimal(row.getCell(4, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue());// 精度
						entity.setPrimaryKey("*"
								.equals(row.getCell(5, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue()));// 是否主鍵
						entity.setNotNull("*"
								.equals(row.getCell(6, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue()));// 是否非空
						// 存入list
						entities.add(entity);
					}
				}
			} else {
				System.out.println("找不到指定的文件");
				return null;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		TableEntity tableEntity = new TableEntity();
		tableEntity.setEntities(entities);
		tableEntity.setDatabaseName(databaseName);
		tableEntity.setLogicalTableName(logicalTableName);
		tableEntity.setPhysicalTableName(physicalTableName);
		return tableEntity;
	}

	/**
	 * 將表實體轉換為sql並輸出為txt
	 * 
	 * @param tableEntity
	 */
	public void convertSQL(TableEntity tableEntity) {
		StringBuffer sql = new StringBuffer();
		sql.append("CREATE TABLE `");
		sql.append(tableEntity.getDatabaseName());
		sql.append("`.`");
		sql.append(tableEntity.getPhysicalTableName());
		sql.append("` (");
		// CREATE TABLE `databaseName`.`tablePhysicalName` (
		List<ColumnEntity> cellEnties = tableEntity.getEntities();
		// 主鍵
		String primaryKey = null;
		// 獲取主鍵
		for (ColumnEntity item : cellEnties) {
			// 將pk為true的設為主鍵
			if (item.isPrimaryKey()) {
				primaryKey = item.getPhysicalColumnName();
				break;
			}
		}
		// 循環列
		for (ColumnEntity item : cellEnties) {
			sql.append(" `");
			sql.append(item.getPhysicalColumnName().trim());
			sql.append("` ");
			// `physicalColumnName`

			// 根據NOT NULL 來拼接
			if (item.isNotNull()) { // 如果不允許為空,則拼接NOT NULL
				//類型
				String type = item.getType().toLowerCase();
				//類型轉換
				if(type.indexOf("varchar")!=-1) {
					type= TableTypeConstant.VARCHAR;
				}else if (type.indexOf("number")!=-1) {
					type=TableTypeConstant.INT;
					//默認長度
					if(item.getLength()==null||item.getLength().isEmpty()) {
						item.setLength("11");
					}
				}else if(type.indexOf("char")!=-1) {
					type=TableTypeConstant.CHAR;
				}

				
				// 根據類型選擇是否拼接長度
				if (TableTypeConstant.CHAR.equals(type) || TableTypeConstant.VARCHAR.equals(type)) { // 文本需要拼接長度
					sql.append(type);
					sql.append("(");
					sql.append(item.getLength());
					sql.append(") CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '");
				} else if (TableTypeConstant.TEXT.equals(type) || TableTypeConstant.LONG_TEXT.equals(type)) { // 文本不需要拼接長度
					sql.append(type);
					sql.append(" CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '");
				} else if (TableTypeConstant.DATE.equals(type)) { // 時間不需要拼接長度
					sql.append(type);
					sql.append(" NOT NULL COMMENT '");
				} else if (TableTypeConstant.DATE_TIME.equals(type)||TableTypeConstant.TIME_STAMP.equals(type)) { // 時間需要拼接長度 並且長度為0
					sql.append(type);
					sql.append("(0) NOT NULL COMMENT '");
				} else if (TableTypeConstant.INT.equals(type)) { // 數字需要拼接長度
					sql.append(type);
					sql.append("(");
					sql.append(item.getLength());
					sql.append(")  NOT NULL COMMENT '");
				}
			} else { // 如果允許為空,則拼接 NULL DEFAULT NULL
				
				String type = item.getType().toLowerCase();
				//類型轉換
				if(type.indexOf("varchar")!=-1) {
					type=TableTypeConstant.VARCHAR;
				}else if (type.indexOf("number")!=-1) {
					type=TableTypeConstant.INT;
					//默認長度
					if(item.getLength()==null||item.getLength().isEmpty()) {
						item.setLength("11");
					}
				}else if(type.indexOf("char")!=-1) {
					type=TableTypeConstant.CHAR;
				}
				
				// 根據類型選擇是否拼接長度
				if (TableTypeConstant.CHAR.equals(type) || TableTypeConstant.VARCHAR.equals(type)) { // 文本需要拼接長度
					sql.append(type);
					sql.append("(");
					sql.append(item.getLength());
					sql.append(") CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '");
				} else if (TableTypeConstant.TEXT.equals(type) || TableTypeConstant.LONG_TEXT.equals(type)) { // 文本不需要拼接長度
					sql.append(type);
					sql.append(" CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '");
				} else if (TableTypeConstant.DATE.equals(type)) { // 時間不需要拼接長度
					sql.append(type);
					sql.append(" NULL DEFAULT NULL COMMENT '");
				} else if (TableTypeConstant.DATE_TIME.equals(type)||TableTypeConstant.TIME_STAMP.equals(type)) { // 時間需要拼接長度 並且長度為0
					sql.append(type);
					sql.append("(0) NULL DEFAULT NULL COMMENT '");
				} else if (TableTypeConstant.INT.equals(type) || TableTypeConstant.BIG_INT.equals(type) || TableTypeConstant.LONG.equals(type)) { // 數字需要拼接長度
					sql.append(type);
					sql.append("(");
					sql.append(item.getLength());
					sql.append(")  NULL DEFAULT NULL COMMENT '");
				}
			}

			// 拼接邏輯列名
			sql.append(item.getLogicalColumnName());
			sql.append("',");
		}

		// 拼接主鍵
		sql.append(" PRIMARY KEY (`");
		sql.append(primaryKey);
		sql.append("`) USING BTREE ) ");
		// 拼接引擎和邏輯表名
		sql.append("ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '");
		sql.append(tableEntity.getLogicalTableName());
		sql.append("'  ROW_FORMAT = Compact;");
		System.err.println(sql);
		try {
			writeTXT("", sql.toString(), tableEntity.getPhysicalTableName() + tableEntity.getLogicalTableName());
			System.out
					.println("已導出:" + tableEntity.getPhysicalTableName() + tableEntity.getLogicalTableName() + ".txt!");
		} catch (Exception e) {
			e.printStackTrace();
			System.err.println("導出文件失敗");
		}
	}

	/**
	 * 將字符串寫入txt並導出
	 * 
	 * @throws Exception
	 */
	public void writeTXT(String path, String value, String fileName) throws Exception {
		File f = new File(path + fileName + ".txt");
		FileOutputStream fos1 = new FileOutputStream(f);
		OutputStreamWriter dos1 = new OutputStreamWriter(fos1);
		dos1.write(value);
		dos1.close();
	}
}

主入口

通過控制台輸入Excel路徑,會在jar包同級目錄下生成包含建表SQL的TXT文件。

public class MainApplication {
	public static void main(String[] args) {
		while(true) {
			Excel excel = new Excel();
			Scanner scanner = new Scanner(System.in);
			System.err.println("請輸入Excel的路徑:");
			String excelPath = scanner.nextLine();
			TableEntity tEntity = excel.readExcel(excelPath);
			if(tEntity==null) {
				continue;
			}
			excel.convertSQL(tEntity);
		}
	}
}

總結

基本上就是解析EXCEL,然后根據數據類型拼接SQL語句。

目前支持情況:

較原文沒啥改動,只是增加了部分字段,處理了部分默認值問題。


免責聲明!

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



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