【问题标题】:How to loop SQL statements?如何循环 SQL 语句?
【发布时间】:2013-04-08 14:23:35
【问题描述】:

我正在尝试为列表中的每个值运行一个新的 SQL 命令。我有以下内容,它只是为我列表中的金额一次又一次地重复相同的值。

请注意,我必须通过我的数组列表中的值的数量循环 SQL,并将每个值作为名称插入 SQL 中,如下所示。

最好的方法是什么,因为这肯定不是。

    int listSize = al.size();

    for(int i = 0; i < listSize; i++) {         
        ResultSet rs1 = name.executeQuery("SELECT sum(hours) FROM PROJECT_TIME WHERE DATE = '"+date+"' AND name = '"+al.listIterator().next()+"'");
        al1.add(rs1.getString(1));
        rs1.close();

    }
    System.out.println(al1);

结果:

[70, 70, 70, 70, 70, 70, 70, 70, 70, 70]

预期结果:

[70, 80, 110, 60, 35, 10, 15, 10, 0, 25]

【问题讨论】:

  • 你可以试试name in (print the list)这个子句吗?
  • al.listIterator().next() 将始终是同一个元素。您需要将迭代器 置于循环之外,然后使用它的方法遍历集合。
  • @NoobUnChained 对不起,你能解释一下你的意思吗?
  • 它总是会给你一个新的迭代器实例和迭代器指向的第一个元素,即总是第一个元素?
  • 顺便说一句,该代码是否存在 SQL 注入攻击的风险?我听到 DB 人员提到 PreparedStatement 以避免此类事情。

标签: java jsp loops jdbc


【解决方案1】:

问题出在

al.listIterator().next()

它总是返回相同的值。因此查询返回相同的结果集字符串,这就是为什么您的结果一直是70

试试这个代码:

int listSize = al.size();

for(int i = 0; i < listSize; i++) {         
    ResultSet rs1 = name.executeQuery("SELECT sum(hours) FROM PROJECT_TIME WHERE DATE = '"+date+"' AND name = '"+al.get(i)+"'");
    while(rs1.next()){
        al1.add(rs1.getString(1));
    }
    rs1.close();

}
System.out.println(al1);

【讨论】:

  • 血腥辉煌。正是我所追求的。你真的是“代码人”:)
【解决方案2】:

每次您创建新的迭代器时,它每次都返回相同的值。试试下面的代码

int listSize = al.size();

    for(int i = 0; i < listSize; i++) {         
        ResultSet rs1 = name.executeQuery("SELECT sum(hours) FROM PROJECT_TIME WHERE DATE = '"+date+"' AND name = '"+al.get(i)+"'");
        al1.add(rs1.getString(1));
        rs1.close();

    }
    System.out.println(al1);

【讨论】:

  • 也为相同的答案投了赞成票。为您的帮助干杯。
【解决方案3】:

请使用

while(rs1.next()){
  System.out.println(rs1.getString(1));
}

【讨论】:

  • 谢谢,但这行不通。如您所见,我在 SQL 中使用了一个迭代器,它需要对 listSize 中的数字重复,它控制我的循环。
  • List 包含会经常更改的名称、值,因此是循环,否则我只会有一个简单的 SQL 语句。带有一个while循环。
【解决方案4】:

简单的答案是您需要在读取结果集之前执行al.get(i) 并调用rs1.next()。在尝试从结果集中读取之前,您还应该检查调用 rs1.next() 是否返回 true

但这忽略了这样一个事实,即在循环中执行查询很糟糕——性能会很糟糕,而且你正在敲击数据库。每次您调用name.executeQuery 时,都会进行一次远程调用,其中包含所有相关开销,并且您正在为您正在迭代的集合中的每个项目执行此操作。如果集合中有 1000 个项目,那就是 1000 个远程调用。此外,使用字符串连接来构建查询意味着数据库必须在每次执行查询时计算查询计划。

要正确执行此操作,您应该使用准备好的语句执行单个查询,然后遍历结果集 - 1 次远程调用 - 类似于:

PreparedStatement preparedStatement = null;
ResultSet resultSet = null;

try
{
  preparedStatement = connection.prepareStatement("SELECT sum(hours) FROM project_time WHERE date = ? AND name IN ?");

  preparedStatement.setDate(1, date);
  preparedStatement.setArray(2, connection.createArrayOf("VARCHAR", al.toArray());

  resultSet = preparedStatement.executeQuery();

  List<String> hours = new ArrayList<String>();

  while (resultSet.next()) 
  {
    hours.add(resultSet.getString(1));
  }

  System.out.println(hours);
}
finally
{
  if (resultSet != null) resultSet.close();
  if (preparedStatement != null) preparedStatement.close();
}

如果不知道您使用的是什么数据库,很难知道语法是否 100%,但您应该了解要点。

【讨论】:

  • 谢谢。我绝对同意我应该使用 prepearedStatements 来减少负载和安全性,并且我将更改我的代码以适应。
【解决方案5】:

像这样设置 for 循环以使用列表中的每个条目:

    for(String name : al) {         
        ResultSet rs1 = name.executeQuery("SELECT sum(hours) FROM PROJECT_TIME WHERE DATE = '"+date+"' AND name = '"+name+"'");
        al1.add(rs1.getString(1));
        rs1.close();

    }
    System.out.println(al1);

【讨论】:

    【解决方案6】:

    你可以用while替换for循环

    Interator i = al.listIterator(); 
    while(i.hasNext()){ 
        String name = i.next(); 
        ResultSet rs1 = name.executeQuery("SELECT sum(hours) FROM PROJECT_TIME WHERE DATE ="+date+"' AND name = '"+name+"'"); 
        while(rs1.next()){ 
          System.out.println(rs1.getString(1)); 
        } 
    }
    

    【讨论】:

    • 不,我没有...之前的帖子有所不同...这里我试图解决迭代器问题。
    • 对我来说看起来一样。
    【解决方案7】:

    当您对 List 使用迭代器时,它会为您提供列表中的第一个元素位置,当调用 Iterator.next() 时,Iterator 会移动到嵌套元素位置。

    `int listSize = al.size();

    for(int i = 0; i < listSize; i++) {         
        ResultSet rs1 = name.executeQuery("SELECT sum(hours) FROM PROJECT_TIME WHERE DATE = '"+date+"' AND name = '"+al.get(i)+"'");
        al1.add(rs1.getString(1));
        rs1.close();
    
    }
    System.out.println(al1);`
    

    【讨论】:

      猜你喜欢
      • 2019-05-15
      • 1970-01-01
      • 2023-03-21
      • 2014-12-14
      • 2013-04-19
      • 1970-01-01
      • 2017-03-09
      • 2015-11-07
      • 2014-07-07
      相关资源
      最近更新 更多