如何用Java将含30列的CSV数据导入SQLite/HSQL数据库?
当然可行!这绝对是Java数据处理里非常常见的场景,哪怕是30列的CSV也完全能搞定。作为新手,你已经迈出了不错的第一步,我来帮你梳理思路、完善代码,再给你一些实用建议~
先修正你代码里的核心问题
你的main方法执行顺序搞反啦!正确的流程应该是:创建数据库 → 创建数据表 → 读取CSV并导入数据,而不是先读CSV再建表。另外你的createTable方法还没写完,语法也有问题,我先帮你补全基础部分:
package importCSV; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Statement; public class ImportData { public ImportData() { } public static void main(String[] args) { String dbName = "tollerName.db"; String csvFilePath = "C:/path/to/your/data.csv"; // 替换成你的CSV文件路径 createDB(dbName); createTable(dbName); importCsvToDatabase(dbName, csvFilePath); } // 创建SQLite数据库(不存在则自动创建) public static void createDB(String name) { String url = "jdbc:sqlite:C:/sqlite/db/" + name; try(Connection conn = DriverManager.getConnection(url)) { if (conn != null) { System.out.println("数据库创建/连接成功!"); } } catch (SQLException e) { e.printStackTrace(); } } // 创建数据表(注意补全剩下的25+列,匹配你的CSV字段) public static void createTable(String name) { String url = "jdbc:sqlite:C:/sqlite/db/" + name; String createTableSql = "CREATE TABLE IF NOT EXISTS projekt_data (" + "Bauprojekt TEXT PRIMARY KEY NOT NULL," + "Bauprojektnummer INTEGER NOT NULL," + "Auftragsnummer INTEGER NOT NULL," + "Trassierung INTEGER NOT NULL," + "JahrSAP INTEGER," + // 这里继续添加剩下的25+列,格式:字段名 类型 [约束], "LetztesFeld TEXT" + ")"; try (Connection conn = DriverManager.getConnection(url); Statement stmt = conn.createStatement()) { stmt.execute(createTableSql); System.out.println("数据表创建成功!"); } catch (SQLException e) { e.printStackTrace(); } } }
核心功能:CSV数据导入
接下来是最关键的导入逻辑,这里给你两种方案:
方案1:原生Java读取(适合简单CSV,无复杂格式)
如果你的CSV是纯逗号分隔、字段里没有逗号/引号这类特殊字符,可以用原生BufferedReader实现:
// 导入CSV数据到数据库 public static void importCsvToDatabase(String dbName, String csvPath) { String url = "jdbc:sqlite:C:/sqlite/db/" + dbName; // 注意:这里的?数量要和你表的列数完全一致(30个) String insertSql = "INSERT INTO projekt_data (Bauprojekt, Bauprojektnummer, Auftragsnummer, Trassierung, JahrSAP, ...) " + "VALUES (?, ?, ?, ?, ?, ...)"; int batchCount = 0; final int BATCH_SIZE = 1000; // 每1000条批量插入,提升效率 try (Connection conn = DriverManager.getConnection(url); PreparedStatement pstmt = conn.prepareStatement(insertSql); BufferedReader br = new BufferedReader(new FileReader(csvPath))) { String line; br.readLine(); // 跳过CSV表头(如果你的CSV有表头的话) while ((line = br.readLine()) != null) { String[] fields = line.split(","); // 逐个设置参数,注意类型匹配(字符串用setString,数字用setInt/setDouble) pstmt.setString(1, fields[0]); pstmt.setInt(2, Integer.parseInt(fields[1])); pstmt.setInt(3, Integer.parseInt(fields[2])); pstmt.setInt(4, Integer.parseInt(fields[3])); pstmt.setInt(5, Integer.parseInt(fields[4])); // 继续设置剩下的25+个字段... pstmt.addBatch(); batchCount++; // 达到批量阈值就执行插入 if (batchCount % BATCH_SIZE == 0) { pstmt.executeBatch(); System.out.println("已插入" + batchCount + "条数据"); } } // 插入剩余的不足批量的数据 pstmt.executeBatch(); System.out.println("所有数据导入完成!共插入" + batchCount + "条"); } catch (SQLException | IOException | NumberFormatException e) { // 捕获数字转换异常,避免一条数据出错导致整个导入失败 System.err.println("导入数据时出错:" + e.getMessage()); e.printStackTrace(); } }
方案2:用OpenCSV库(推荐,处理复杂CSV)
如果你的CSV字段里包含逗号、引号或者换行,原生split会直接失效,这时候用专业的CSV解析库更靠谱。首先在你的项目里添加OpenCSV依赖(Maven为例):
<dependency> <groupId>com.opencsv</groupId> <artifactId>opencsv</artifactId> <version>5.6</version> </dependency>
然后修改导入方法:
import com.opencsv.CSVReader; // ...其他导入语句 public static void importCsvWithOpenCsv(String dbName, String csvPath) { String url = "jdbc:sqlite:C:/sqlite/db/" + dbName; String insertSql = "INSERT INTO projekt_data (Bauprojekt, Bauprojektnummer, Auftragsnummer, Trassierung, JahrSAP, ...) " + "VALUES (?, ?, ?, ?, ?, ...)"; int batchCount = 0; final int BATCH_SIZE = 1000; try (Connection conn = DriverManager.getConnection(url); PreparedStatement pstmt = conn.prepareStatement(insertSql); CSVReader reader = new CSVReader(new FileReader(csvPath))) { String[] nextLine; reader.readNext(); // 跳过表头 while ((nextLine = reader.readNext()) != null) { // 和原生方案一样设置参数,OpenCSV已经帮你处理了特殊字符的拆分 pstmt.setString(1, nextLine[0]); pstmt.setInt(2, Integer.parseInt(nextLine[1])); pstmt.setInt(3, Integer.parseInt(nextLine[2])); // ...补全其他字段 pstmt.addBatch(); batchCount++; if (batchCount % BATCH_SIZE == 0) { pstmt.executeBatch(); System.out.println("已插入" + batchCount + "条数据"); } } pstmt.executeBatch(); System.out.println("数据导入完成!"); } catch (SQLException | IOException e) { e.printStackTrace(); } }
给新手的关键建议
- 数据类型匹配:30列的字段要逐一对应SQLite的类型(TEXT、INTEGER、REAL等),避免类型转换错误。如果CSV里有空值,要考虑用
setNull或者设置默认值。 - 主键冲突处理:如果你的
Bauprojekt字段可能重复,可以把插入语句改成INSERT OR REPLACE INTO ...,避免插入失败。 - 资源自动关闭:全程用
try-with-resources语法,自动关闭Connection、PreparedStatement、BufferedReader这些资源,避免内存泄漏。 - 依赖准备:别忘了导入SQLite的JDBC驱动,Maven依赖如下:
<dependency> <groupId>org.xerial</groupId> <artifactId>sqlite-jdbc</artifactId> <version>3.45.2.0</version> </dependency> - 测试小数据:先拿几行测试数据跑通流程,再导入完整的CSV,避免一次性处理大量数据出错。
内容的提问来源于stack exchange,提问作者PilotKot
相关产品推荐
相关产品推荐

