在嵌套循环中使用准备好的语句时的最佳方式

Posted

技术标签:

【中文标题】在嵌套循环中使用准备好的语句时的最佳方式【英文标题】:Best way when using prepared statement in nested loop 【发布时间】:2015-12-14 13:59:08 【问题描述】:

在嵌套循环中执行多个查询时,最好的方法是什么?我有如下代码:

String sql1 = SQLContainer.SOME_SQL;
String sql2 = SQLContainer.SOME_SQL2;
    if (someThings != null) 
        for (Some some : someThings) 
            ps = con.prepareStatement(sql1);
            ps.setString(1, some.name);
            ps.setString(2, some.type);
            ps.executeUpdate();

            if (some.getParams != null) 
                for (Some2 some2 : some.params) 
                    ps = con.prepareStatement(sql2);
                    ps.setString(1, some2.name);
                    ps.setString(2, some2.value);
                    ps.setString(3, some2.type);
                    ps.executeUpdate();
                
            
        
    
    这样使用可以吗? 我应该创建 2 个不同的循环,一个用于 sql1,一个用于 sql2? 我应该为不同的循环创建 2 种不同的方法吗? 或者我该怎么办?

sqls 只是插入语句,两个 sqls 以某种方式相互关联。当我也从 some.params 收到错误时,我不想插入一些。

【问题讨论】:

【参考方案1】:

除非你做对了,否则循环中的 SQL 性能会很差。

在您的情况下,我强烈建议使用批处理 SQL

第一个循环看起来像这样:

    int p1Count = 0;
    int BATCHSIZE = 1000;
    if (something) 
            PreparedStatement ps1 = con.prepareStatement(SQLContainer.SOME_SQL);        
            for (Some some : someThing) 
                ps1.setString(1, some.name);
                ps1.setString(2, some.type);
                ps1.addBatch();
                if(++p1Count % BATCHSIZE == 0) 
                    ps1.executeBatch();
                
                ... 
            
            ps1.executeBatch();

同样,您应该拆分循环以一次执行 一种 SQL - 所以首先对 some 执行所有更新,然后(在第二个循环中) 为 some2

做所有更新

只要您将其保留在一笔交易中,就可以了。

可以也可能保留嵌套代码 - 但是您的 s1 和 s2 计数器将是独立的,因此您真的不应该在启用自动提交的情况下这样做,因为没有办法告诉您哪些项目已处理,哪些未处理。

在这种情况下,你最终会得到类似的东西

        int p1Count = 0;
        int p2Count = 0;
        int BATCHSIZE = 1000;
        if (something) 
            try(PreparedStatement ps1 = con.prepareStatement(SQLContainer.SOME_SQL);
                   PreparedStatement ps2 = con.prepareStatement(SQLContainer.SOME_SQL2))                       
              for (Some some : someThing) 
                ps1.setString(1, some.name);
                ps1.setString(2, some.type);
                ps1.addBatch();
                if(++p1Count % BATCHSIZE == 0) 
                    ps1.executeBatch();
                
                if (somethingElse) 
                    for (Some2 some2 : some.param) 
                        ps2.setString(1, some2.name);
                        ps2.setString(2, some2.value);
                        ps2.setString(3, some2.type);
                        ps2.addBatch();
                        if(++p2Count % BATCHSIZE == 0) 
                            ps2.executeBatch();
                        
                    
                
              
              p2.executeBatch();
              p1.executeBatch();
             //End try-with-resource
        

【讨论】:

【参考方案2】:

把它放在一个私有函数中并传递参数,即sql1、some.name、some.type

ps = con.prepareStatement(sql1);
ps.setString(1, some.name);
ps.setString(2, some.type);
ps.executeUpdate();

根据条件调用不同参数的同一个函数。

【讨论】:

Sqls和参数不同。我更新了代码和问题。是的,我可以制作不同的方法,但为什么会更好?

以上是关于在嵌套循环中使用准备好的语句时的最佳方式的主要内容,如果未能解决你的问题,请参考以下文章

在JAVA中如何跳出当前的多重嵌套循环?

有两个循环,他们是嵌套关系,在内循环中使用break将终止哪一个循环?

为啥我的代码在执行时的初始嵌套 for 循环中进入无限循环?

打破 JavaScript 中嵌套循环的最佳方法是啥?

在VB中 for 循环嵌套语句的用法语解释(必须清楚!!)

跳出嵌套循环