Excel转SQL脚本工具:从手工拼SQL到一键导出
简介这是一份面向Java开发者与数据处理人员的实用工具资源聚焦于将Excel表格数据自动解析并生成可执行的SQL脚本再通过JDBC连接写入数据库适用于数据迁移、批量导入与数据分析等场景。压缩包共56个文件约24.48MB包含21个jar依赖、20个class与11个java源码另有classpath配置、xls测试模板及可执行jar结构完整便于直接运行与二次开发。资源核心围绕Apache POI解析Excel、构造INSERT等SQL语句、配置数据库驱动并执行连接操作展开源码可帮助理解从工作簿读取到字段映射、再到JDBC执行与异常处理的完整链路。目前已有979人学习下载适合熟悉Java与关系型数据库、希望提升数据操作效率的开发者参考借鉴。1. 读取Excel生成Sql脚本从手工拼SQL到一键导出你有没有遇到过这种场景业务方丢过来一个 Excel里面几十上百行数据让你导入数据库。手动写 INSERT 语句复制粘贴到凌晨三点还容易把和,搞混。这个项目就是来解决这个问题的——读取 Excel 文件自动解析表头和每一行数据生成可直接执行的 SQL 脚本。它适合经常做数据迁移、批量导入、测试数据构造的后端开发和数据工程同学。技术栈上核心依赖 JDBC 连接数据库做元数据校验用 POI 或 EasyExcel 解析表格再通过模板引擎拼装 SQL。整个流程不复杂但细节很多比如字段类型映射、空值处理、特殊字符转义这些才是真正决定脚本能不能跑通的关键。2. 项目定位与技术选型为什么不用 Navicat 导入2.1 这个工具解决的具体问题Navicat、DBeaver 这类工具确实有导入功能但它们通常要求你先建好表而且对 Excel 的格式要求很严格——表头必须和列名完全一致日期格式稍微不对就报错。更麻烦的是当你要把 Excel 数据生成 SQL 脚本发给别人执行时这些工具没法直接导出成可读的.sql文件。这个项目的定位很明确把 Excel 当作数据源把 SQL 脚本当作交付物。你不需要提前建表工具会根据 Excel 的表头自动推断字段名结合 JDBC 读取目标表的元数据如果表已存在生成带类型转换的 INSERT 语句。常见做法是先用 JDBC 的DatabaseMetaData拿到列类型再把 Excel 单元格的值转成对应的 SQL 字面量。2.2 技术栈拆解组件选型作用Excel 解析Apache POI / EasyExcel读取 .xlsx 和 .xls 文件数据库连接JDBC获取表结构、校验字段SQL 生成字符串模板 / MyBatis 动态 SQL拼装 INSERT 语句构建工具Maven / Gradle依赖管理运行方式命令行 / 单元测试传入文件路径和连接参数选 POI 还是 EasyExcel如果 Excel 文件不大几千行以内POI 的XSSFWorkbook足够用API 也直观。如果动辄几万行EasyExcel 的流式读取更稳内存占用低。我一般会先问清楚数据量再决定用哪个。2.3 核心流程设计整个工具的执行链路可以拆成四步读取 Excel加载文件拿到第一个 Sheet解析表头行和数据行。连接数据库通过 JDBC 建立连接查询目标表是否存在。类型映射根据数据库列类型把 Excel 单元格的值转成 SQL 字面量。生成脚本按行拼装 INSERT 语句写入.sql文件。这四步里第三步最容易翻车。比如 Excel 里看起来是数字的单元格POI 可能读出来是1.0而不是1日期单元格可能读出来是一个数字序列号。这些坑后面会专门讲。3. 核心模块拆解从 Excel 单元格到 SQL 字面量3.1 Excel 解析与表头处理先看读取 Excel 的代码。这里用 POI 举例重点是处理不同类型的单元格public ListMapString, Object readExcel(String filePath) throws IOException { ListMapString, Object rows new ArrayList(); try (FileInputStream fis new FileInputStream(filePath); Workbook workbook new XSSFWorkbook(fis)) { Sheet sheet workbook.getSheetAt(0); Row headerRow sheet.getRow(0); ListString headers new ArrayList(); // 解析表头去掉空格和特殊字符 for (Cell cell : headerRow) { String header cell.getStringCellValue().trim() .replaceAll([^a-zA-Z0-9_], _); headers.add(header); } // 从第二行开始读数据 for (int i 1; i sheet.getLastRowNum(); i) { Row row sheet.getRow(i); if (row null) continue; MapString, Object rowData new LinkedHashMap(); for (int j 0; j headers.size(); j) { Cell cell row.getCell(j); rowData.put(headers.get(j), getCellValue(cell)); } rows.add(rowData); } } return rows; }这段代码有几个关键点表头做了字符替换把中文和特殊符号转成下划线避免生成的 SQL 列名不合法用LinkedHashMap保持列的顺序这样生成的 INSERT 语句字段顺序和 Excel 一致方便核对。getCellValue方法需要根据单元格类型分别处理private Object getCellValue(Cell cell) { if (cell null) return null; switch (cell.getCellType()) { case STRING: return cell.getStringCellValue().trim(); case NUMERIC: if (DateUtil.isCellDateFormatted(cell)) { return new java.sql.Date(cell.getDateCellValue().getTime()); } double num cell.getNumericCellValue(); // 处理 1.0 变成 1 的问题 if (num Math.floor(num) !Double.isInfinite(num)) { return (long) num; } return num; case BOOLEAN: return cell.getBooleanCellValue(); case BLANK: return null; default: return cell.toString(); } }数字类型的处理是血泪经验Excel 里输入100POI 读出来是100.0如果直接拼进 SQL数据库里就变成浮点数了。所以这里判断如果是整数就转成long。日期类型也要单独处理否则会得到一个像45123这样的序列号。3.2 JDBC 获取表结构与类型映射生成 SQL 之前最好先连上数据库看看目标表长什么样。这样能知道每个字段的真实类型避免把字符串塞进 INT 列public MapString, String getTableColumns(Connection conn, String tableName) throws SQLException { MapString, String columns new LinkedHashMap(); DatabaseMetaData metaData conn.getMetaData(); try (ResultSet rs metaData.getColumns(null, null, tableName, null)) { while (rs.next()) { String columnName rs.getString(COLUMN_NAME); String columnType rs.getString(TYPE_NAME); columns.put(columnName.toLowerCase(), columnType); } } return columns; }拿到列类型后在拼 SQL 时就可以做针对性处理。比如VARCHAR类型的值要加单引号并转义INT类型直接拼数字DATE类型要格式化成2024-01-15这种形式。转义函数长这样private String escapeSqlValue(Object value, String columnType) { if (value null) return NULL; if (columnType.contains(INT) || columnType.contains(DECIMAL) || columnType.contains(FLOAT) || columnType.contains(DOUBLE)) { return value.toString(); } if (columnType.contains(DATE) || columnType.contains(TIME)) { return value.toString() ; } // 字符串类型转义单引号和反斜杠 String str value.toString() .replace(\\, \\\\) .replace(, ); return str ; }注意字符串转义这里用了而不是\因为标准 SQL 里单引号转义就是写两个单引号这样兼容性更好。3.3 生成 INSERT 脚本最后一步是把前面拿到的数据拼成完整的 SQL 语句public void generateSql(ListMapString, Object rows, MapString, String columns, String tableName, String outputPath) throws IOException { try (BufferedWriter writer new BufferedWriter(new FileWriter(outputPath))) { for (MapString, Object row : rows) { StringBuilder sql new StringBuilder(INSERT INTO ) .append(tableName).append( (); // 字段名 sql.append(String.join(, , row.keySet())); sql.append() VALUES (); // 字段值 ListString values new ArrayList(); for (Map.EntryString, Object entry : row.entrySet()) { String colType columns.getOrDefault( entry.getKey().toLowerCase(), VARCHAR); values.add(escapeSqlValue(entry.getValue(), colType)); } sql.append(String.join(, , values)); sql.append();); writer.write(sql.toString()); writer.newLine(); } } }生成的脚本每行一条 INSERT末尾带分号可以直接在数据库客户端里批量执行。如果数据量很大可以考虑每 1000 条包一个事务或者用INSERT INTO ... VALUES (...), (...), ...的批量语法减少网络往返。4. 避坑与常见问题排查4.1 数字变成 1.0 或者科学计数法现象Excel 里明明是100生成的 SQL 里变成100.0或者长数字变成1.23456789E8。原因POI 把所有数字都当double读这是 Excel 底层的存储方式决定的。解决在getCellValue里判断如果是整数就转long如果是小数就用BigDecimal格式化避免科学计数法。对于手机号、身份证号这种长数字建议在 Excel 里就设成文本格式读取时按字符串处理。4.2 日期字段读出来是一串数字现象Excel 里是2024-01-15读出来是45306。原因Excel 内部用序列号存日期1900 年 1 月 1 日是 1。解决用DateUtil.isCellDateFormatted(cell)判断如果是日期格式就用cell.getDateCellValue()拿Date对象再格式化成yyyy-MM-dd字符串。4.3 表头有空格或特殊字符导致 SQL 报错现象生成的 SQL 执行时报Unknown column user name。原因Excel 表头里带了空格、中文括号、斜杠等字符。解决解析表头时统一做清洗把非字母数字下划线的字符替换成下划线连续下划线合并成一个。如果表头是中文要么手动映射成英文列名要么在数据库里用反引号包住列名。4.4 空单元格处理不当导致 NOT NULL 约束失败现象数据库报Column name cannot be null。原因Excel 里空单元格读出来是null直接拼成NULL塞进 SQL。解决在生成 SQL 前检查目标列的约束如果是NOT NULL且没有默认值要么给一个空字符串要么跳过这一行并记录日志。我一般会生成一个error.log把有问题的行号和数据打出来方便人工核对。4.5 大数据量导致内存溢出现象读取几万行的 Excel 时程序卡死或抛OutOfMemoryError。原因XSSFWorkbook会把整个文件加载到内存。解决换成 EasyExcel 的流式读取或者用 POI 的SXSSFWorkbook但它是写用的。读大文件推荐 EasyExcel它基于 SAX 解析内存占用稳定。如果坚持用 POI可以调大 JVM 的-Xmx但治标不治本。5. 二次开发与扩展思路5.1 支持多 Sheet 和自定义列映射现在的代码只读了第一个 Sheet实际项目里经常需要指定 Sheet 名或者按索引读取。改造起来不难把workbook.getSheetAt(0)换成workbook.getSheet(sheetName)就行。更实用的是加一个列映射配置比如用 JSON 文件定义{Excel表头: 数据库列名}这样业务方改表头也不用改代码。{ 用户姓名: user_name, 手机号: phone, 注册日期: register_date }读取映射后在解析表头时做一次转换后面的流程完全不用动。5.2 生成批量 INSERT 提升执行效率逐条 INSERT 在数据量大时执行很慢可以改成每 N 条合并成一条语句// 每 500 条拼一个 INSERT StringBuilder batchSql new StringBuilder(INSERT INTO tableName (); batchSql.append(String.join(, , columns.keySet())).append() VALUES ); ListString valueGroups new ArrayList(); for (MapString, Object row : batch) { ListString values new ArrayList(); for (String col : columns.keySet()) { values.add(escapeSqlValue(row.get(col), columns.get(col))); } valueGroups.add(( String.join(, , values) )); } batchSql.append(String.join(, , valueGroups)).append(;);注意批量插入时单条 SQL 不能太长MySQL 默认max_allowed_packet是 4MB超过会报错。500 条一批通常比较安全具体看字段数量和值的大小。5.3 增加数据校验和错误报告生产环境用的时候最怕生成一堆 SQL 结果执行到一半报错。建议在生成脚本前加一层校验检查必填字段是否为空、数字字段是否合法、日期格式是否正确。校验不通过的行不生成 SQL而是输出到错误报告里。ListString errors new ArrayList(); for (int i 0; i rows.size(); i) { MapString, Object row rows.get(i); if (row.get(user_name) null || row.get(user_name).toString().isEmpty()) { errors.add(第 (i 2) 行user_name 为空); continue; } // 其他校验... } if (!errors.isEmpty()) { Files.write(Paths.get(error.log), errors); }这样跑完一遍能执行的 SQL 已经生成好了有问题的行也列得清清楚楚直接发给业务方核对就行。5.4 一个容易忽略的细节事务和编码生成的 SQL 文件默认用系统编码写入如果数据库是 UTF-8 而系统是 GBK中文会乱码。建议在FileWriter里显式指定StandardCharsets.UTF_8。另外如果生成的脚本要在命令行里执行记得在文件开头加SET NAMES utf8mb4;避免客户端编码不一致。从那以后我每次生成 SQL 脚本都会先拿 10 行数据跑一遍确认字段类型、日期格式、中文编码都没问题再全量生成。这个习惯帮我省了很多返工的时间。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

从端口占用到一键清理:一个跨平台命令行工具的开发与实践

从端口占用到一键清理:一个跨平台命令行工具的开发与实践

每次切换端口空间的那两行命令,我真的打到快吐了。新起一个本地服务、跑一下自动化用例、重新烧录调试程序,只要看到那句“Address already in use”或者“port is already in use”,接下来就是一套肌肉记忆:开新终端、查PID、复制…

2026/10/18 9:25:28 阅读更多 →
Excel转SQL工具:POI+JDBC实现数据迁移与批量插入

Excel转SQL工具:POI+JDBC实现数据迁移与批量插入

简介:这是一份面向Java开发者与数据库运维人员的数据处理工具源码包,用于将Excel表格数据自动解析并生成可执行的SQL脚本,再通过JDBC连接写入目标数据库,适用于数据迁移、批量导入与数据分析等场景。压缩包共56个文件,…

2026/10/18 9:25:28 阅读更多 →
Notepad++ 安装包下载与配置全指南:编码、插件、正则避坑

Notepad++ 安装包下载与配置全指南:编码、插件、正则避坑

简介:Notepad安装包面向Windows平台下需要轻量级文本与代码编辑工具的程序员、运维人员及普通用户,用于替代系统自带记事本,解决日常文本处理、代码编写与调试中的效率问题。压缩包共104个文件,约3.9MB,以89个xml配置文…

2026/10/18 9:25:28 阅读更多 →

最新新闻

OpenClaw智能体全流程部署:从环境配置到多Agent自动化实战

OpenClaw智能体全流程部署:从环境配置到多Agent自动化实战

说实话,我早就受够了在不同AI工具之间来回切换、复制粘贴、手工串联任务的繁琐日子。直到我把一个开源智能体框架OpenClaw完整部署下来,从环境准备、角色配置、工具接入到多流程联动跑通,才发现原来AI智能体全流程操作并没有想象中那么玄乎&a…

2026/10/18 19:13:14 阅读更多 →
Moaw框架复现:视频运动迁移提速13倍精度翻倍的工程实践

Moaw框架复现:视频运动迁移提速13倍精度翻倍的工程实践

视频运动迁移这个方向,这几年真的被"复杂适配"折磨得不轻。做过这套东西的人都懂:模型换一个数据集就要重新标关键点、重新对齐人物骨架、重新调一堆超参数,稍有不慎生成结果不是脸崩就是手势僵硬,跑一次实验的周期以天…

2026/10/18 19:13:14 阅读更多 →
一台机器同时跑4路对话:halogen-flash-server的KV池、并发槽位与1M上下文配置全攻略

一台机器同时跑4路对话:halogen-flash-server的KV池、并发槽位与1M上下文配置全攻略

【免费下载链接】halogen-flash-server The fastest way to run Qwen3.8-Flash-Next on Strix Halo (gfx1151) 项目地址: https://gitcode.com/gh_mirrors/ha/halogen-flash-server 点击查看 免费下载 halogen-flash-server 是一个为 AMD Strix Halo(gf…

2026/10/18 19:13:14 阅读更多 →
Linux namespace进阶:rootless容器权限模型与资源回收实战

Linux namespace进阶:rootless容器权限模型与资源回收实战

这个系列走到第三篇,意味着你大概率已经亲手跑过 unshare、nsenter,也见识过 mount namespace 切换目录视图那套玩法了。part3-advanced 这一篇,我想集中聊那些在真实环境里才会暴露出来的问题:rootless 容器到底靠什么跑起来&…

2026/10/18 19:13:14 阅读更多 →
内网渗透核心工具Cobalt Strike:从部署到实战全流程详解

内网渗透核心工具Cobalt Strike:从部署到实战全流程详解

聊内网渗透和红队模拟,Cobalt Strike(简称CS)是绕不开的一个平台。它把拿到初始权限之后的所有后渗透动作——命令控制信道、会话管理、横向移动、提权、凭据获取、痕迹清理、甚至团队协同作战——集中到了一个可视化的GUI里。很多授权渗透测…

2026/10/18 19:13:14 阅读更多 →
谐波平衡法MATLAB实现指南:从残差函数到频响曲线

谐波平衡法MATLAB实现指南:从残差函数到频响曲线

简介:这份MATLAB谐波平衡法实现资源,面向从事非线性电路、电力电子装置及动力系统频域分析的工程师、科研人员和学生,针对手工推导谐波平衡方程组繁琐、难以快速验证的问题,围绕将时域非线性方程经傅立叶级数展开、在频域离散为代…

2026/10/18 19:12:14 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →