Java:如何使用用于 Sql Server 的 java jdbc 执行带有标识列的批量插入

Posted

技术标签:

【中文标题】Java:如何使用用于 Sql Server 的 java jdbc 执行带有标识列的批量插入【英文标题】:Java: how to perform batch insert with identity column using java jdbc for Sql Server 【发布时间】:2019-03-18 15:06:34 【问题描述】:

我有一个 csv 文件,我需要使用 SQLServerBulkCopy 将其写入 Sql Server 表。我正在使用SQLServerBulkCSVFileRecord 从文件中加载数据。

目标表的结构如下:

create table TEST
(
    ID int identity,
    FIELD_1 int,
    FIELD_2 varchar(20)
)

csv 文件的结构如下:

4279895;AA00000002D
4279895;AA00000002D
4279895;AA00000002D
4279896;AA00000003E
4279896;AA00000003E
4279896;AA00000003E

您可以看到 csv 中不存在 ID(身份)列,我需要数据库在插入时自动添加身份值。 我的问题是,只要表有标识列,批量插入就不起作用,我收到以下错误:

com.microsoft.sqlserver.jdbc.SQLServerException: Source and destination schemas do not match.
    at com.microsoft.sqlserver.jdbc.SQLServerBulkCopy.validateColumnMappings(SQLServerBulkCopy.java:1749)
    at com.microsoft.sqlserver.jdbc.SQLServerBulkCopy.writeToServer(SQLServerBulkCopy.java:1579)
    at com.microsoft.sqlserver.jdbc.SQLServerBulkCopy.writeToServer(SQLServerBulkCopy.java:606)

这是相关代码:

try (
        Connection targetConnection = DriverManager.getConnection(Configuration.TARGET_CONNECTION_URL);
        SQLServerBulkCopy bulkCopy = new SQLServerBulkCopy(targetConnection);
        SQLServerBulkCSVFileRecord fileRecord = new SQLServerBulkCSVFileRecord(csvPath, Charsets.UTF_8.toString(), ";", false);
) 

    SQLServerBulkCopyOptions copyOptions = new SQLServerBulkCopyOptions();
    copyOptions.setKeepIdentity(false);

    bulkCopy.setBulkCopyOptions(copyOptions);

    fileRecord.addColumnMetadata(1, null, java.sql.Types.INTEGER, 0, 0); // FIELD_1 int    
    fileRecord.addColumnMetadata(2, null, java.sql.Types.VARCHAR, 20, 0); // FIELD_2 varchar(20)

    bulkCopy.setDestinationTableName("TEST");                
    bulkCopy.writeToServer(fileRecord);



catch (Exception e) 

    // [...]


如果我从表中删除标识列,则批量插入成功结束。使用 java jdbc for Sql Server 执行身份批量插入哪个是正确的?

【问题讨论】:

【参考方案1】:

我觉得你不需要设置这个选项copyOptions.setKeepIdentity(false);

删除此行后尝试。你也可以参考这个帖子SqlBulkCopy Insert with Identity Column

【讨论】:

【参考方案2】:

如果您有一个带有空白值的前导列 Helen,则将在插入时生成标识。根据设置,即使第一列不为空,它也可能生成新标识。

所以要么添加一个额外的列,要么使用另一个(临时)表。

顺便说一句,如果你有一个非常大的表,命令行 bcp 实用程序是最快的。与 Jdbc 批量插入相比,从体验速度提高 5 倍。

【讨论】:

以上是关于Java:如何使用用于 Sql Server 的 java jdbc 执行带有标识列的批量插入的主要内容,如果未能解决你的问题,请参考以下文章

sql server 中如何查看自定义函数的源代码?

如何使用 Sql Server 2008 获取用于插入到 select 中的 scope_identity 列表?

如何使用 SSMA(用于访问 SQL Server)将具有不同列的表迁移到现有表中?

java 连接SQL Server

使用 Spring JPA 在 H2 和 Sql Server 中持久化的 Java UUID

java - 如何在java jdbc中使用sqoop从sql server导入hive?