如何在一条语句中将多行插入 DB2?

Posted

技术标签:

【中文标题】如何在一条语句中将多行插入 DB2?【英文标题】:How do I insert multilple rows into a DB2 in one statement? 【发布时间】:2018-09-17 19:58:10 【问题描述】:

我正在使用 Java 和 jdbc 驱动程序来建立到 DB2 数据库的连接。我正在尝试使用单个语句将多行插入表中。

以下是我的代码:

 public void createResources(List<Resources> addedResources)
        throws SQLException

    Connection conn = null;
    PreparedStatement statement = null; 
     int i = 0; 

     String values = "INSERT INTO GROUPS (GROUP_NAME, ENTRY_NAME, 
ENTRY_TYPE, LAST_REQ, CREATE_BY, REQ_BY, LAST_CHANGED, LAST_REQ_TIME) VALUES 
 " +  System.getProperty("line.separator");

    while(i < addedResources.size())

        Timestamp LAST_CHANGED = 
Timestamp.valueOf(addedResources.get(i).getLAST_CHANGED().trim());
        Timestamp LAST_REQ_TIME = 
Timestamp.valueOf(addedResources.get(i).getLAST_REQ_TIME().trim());

        values = values + "('" + 
addedResources.get(i).getGROUP_NAME().trim() + "', '" + 

addedResources.get(i).getENTRY_NAME().trim() + "', '" + 

addedResources.get(i).getENTRY_TYPE().trim() + "', '" +

addedResources.get(i).getLAST_REQ().trim() + "', '"   +

addedResources.get(i).getCREATE_BY().trim() + "', '"  +

addedResources.get(i).getREQ_BY().trim()   + "', '"   +
                                      LAST_CHANGED + "', '"   +
                                      LAST_REQ_TIME + "')," + 
System.getProperty("line.separator"); 


    i = i + 1;
       
    values = values.substring(0,values.trim().length()-1);
    Log(Integer.toString(values.length()));
    Log(values);

    try 

         // Get the DB connection
        conn = this.ds.getConnection();
        conn.setAutoCommit(false);

        // Prepare the statement and populate with data
        statement = conn.prepareStatement(values);



        // Perform the INSERT operation
        statement.executeUpdate();

        //Commit the changes 
        conn.commit();
        Log("Employee Successfully Added!");
    
    finally


        // Any exceptions will be propagated

        // Close database objects, regardless of what happened
        if ( statement != null ) 
            statement.close();
        
        if ( conn != null ) 
            conn.close();
        

    



   

总而言之,我有一个循环遍历 List 中的对象并延长插入语句,直到它包含 ArrayList 中的所有行。然后,当循环完成时,我清理字符串的末尾,并尝试执行该语句。

下面是执行方法时查询语句的样例:

INSERT INTO GROUPS (GROUP_NAME, ENTRY_NAME, ENTRY_TYPE, LAST_REQ, CREATE_BY, 
REQ_BY, LAST_CHANGED, LAST_REQ_TIME) VALUES 
('JOHN', 'TEST1', 'FILE', 'N/A', 'SSDP071', 'N/A', '2018-09-17 
19:36:34.004', '2018-09-17 19:36:34.004'),
('JOHN', 'TEST2', 'FILE', 'N/A', 'SSDP071', 'N/A', '2018-09-17 
19:36:37.771', '2018-09-17 19:36:37.771'),
('JOHN', 'TEST3', 'FILE', 'N/A', 'SSDP071', 'N/A', '2018-09-17 
19:36:42.021', '2018-09-17 19:36:42.021')

我的代码尝试执行并抛出以下错误:

[9/17/18 19:36:42:834 GMT] 00000557 SystemOut O com.ibm.db2.jcc.am.SqlSyntaxErrorException:[jcc][50053][12311][4.22.37] T2zOS 异常: [jcc][T2zos]T2zosPreparedStatement.readPrepareDescribeOutput_:nativePrepareInto:1583: DB2 引擎 SQL 错误,SQLCODE = -104,SQLSTATE = 42601,错误标记 = ,;FOR NOT ATOMIC ERRORCODE=-104,SQLSTATE=42601

我的错误标记是一个逗号,我不确定它指的是哪个。有没有办法在 DB2 表中插入多行?帮助将不胜感激!

【问题讨论】:

认为你的最终陈述会是这样吗,还是你真的把它打印出来了?您是否尝试从日志中复制它并在其中执行它,比如 Db2 CLP?您不使用参数化语句的任何原因? 是的,这不是标准 SQL。 Microsoft SQL Server 支持这一点,但我相当肯定 DB2 不支持。您必须发出多个 INSERT 语句。 是的。该声明来自系统输出 一次一个。感谢您的输入。对这些东西很陌生。只是试图验证我不是简单地输入错误或误解了逻辑 我使用的是 DB2 版本 12 【参考方案1】:

您可以改用批处理语句:

String values = "INSERT INTO GROUPS " +
"(GROUP_NAME,ENTRY_NAME,ENTRY_TYPE,LAST_REQ,CREATE_BY,REQ_BY,LAST_CHANGED,LAST_REQ_TIME) " +
"VALUES (?,?,?,?,?,?,?,?)";

// ... 

statement = conn.prepareStatement(values);

// ... 

while(i < addedResources.size())
   statement.setString(addedResources.get(i)).getGROUP_NAME().trim());
   statement.setString(addedResources.get(i)).getENTRY_NAME().trim());

   // ...  

   statement.addBatch();

statement.executeBatch();

【讨论】:

这是一个有效的方法。非常感谢,也感谢关于嵌入的建议。我是在我的环境类型中编写程序的新手,所以我仍在学习如何以更安全的方式编写程序。我会在此基础上进行调整。【参考方案2】:

您似乎正在为 z/OS 使用“JDBC 和 SQLJ 类型 2 连接驱动程序”,因此我假设您的 Db2 服务器在 z/OS 上运行。

Db2 for z/OS 支持 jdbc、静态 SQL 和动态 SQL 的多行插入,如果有很多行要频繁插入,那么使用多行插入是明智的。它使用了与您的问题中显示的不同的方法(即不使用您尝试的 VALUES 子句)。

驱动程序属性enableMultiRowInsertSupport 可用,应默认启用。如果您希望多行插入是原子的,请注意驱动程序属性atomicMultiRowInsert

研究 jdbc 示例(在末尾)this page。有关驱动程序设置的详细信息,请参阅 Db2 知识中心。

【讨论】:

以上是关于如何在一条语句中将多行插入 DB2?的主要内容,如果未能解决你的问题,请参考以下文章

如何制作将生成 SQL 以在一条语句中插入多个值的 HQL?

如何在mysql中将单行插入查询重构为多行插入查询?

如何在一列中将多个数据插入数据库[重复]

如何在 Go 中将变量插入到多行(反引号)字符串中?

Sql 从一个表列中选择一个最小值,并在一个 SQL 语句中将结果插入到另一个表列中

使用 JdbcTemplate 插入多行