如何循环执行SQL语句?

4

我试图为列表中的每个值运行一个新的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)这个语句吗? - AllTooSir
3
al.listIterator().next() 总是返回相同的元素。你需要在循环获取迭代器,然后使用其方法遍历集合。 - Andrew Thompson
2
顺便提一下,那段代码是否存在 SQL 注入攻击的风险?我听说数据库专家会使用 PreparedStatement 来避免这种情况。 - Andrew Thompson
抱歉,我通过点赞破坏了你酷炫的“666”声望。 ;) - Andrew Thompson
@AndrewThompson 哈哈.. 那可能是件好事。不是一个很幸运的数字。 :) - Rhys
显示剩余7条评论
7个回答

5
问题出在:
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);

太棒了,正是我想要的。你真的是“代码大师” :) - Rhys

3

每次你创建的迭代器都会返回相同的值。尝试以下代码:

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);

我给了你一个赞,因为你的回答也是正确的。感谢你的帮助,干杯! - Rhys

2
请使用。
while(rs1.next()){
  System.out.println(rs1.getString(1));
}

谢谢,但那样行不通。您可以看到我在SQL中使用了一个迭代器,需要重复执行列表大小的次数,以控制我的循环。 - Rhys
列表包含名称和值,这些值经常会更改,因此需要循环,否则我只需使用一个简单的SQL语句和while循环。 - Rhys

1
简单来说,在从结果集中读取数据之前,您需要执行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();
}

不知道您使用的数据库是哪种,所以很难确定语法是否完全正确,但是您应该可以理解大意。


谢谢。我完全同意我应该使用preparedStatements来减少负载和提高安全性,我会改变我的代码来适应这一点。 - Rhys

0
设置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);

0

你可以用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)); 
    } 
}

不,我没有...之前的帖子是另一回事...这里我正在尝试解决迭代器问题。 - Amit Sharma
在我看来,它看起来完全一样。 - Lightness Races in Orbit

0
当您使用List的迭代器时,它会给您列表中第一个元素的位置,当调用Iterator.next()时,迭代器将移动到下一个元素的位置。
`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);`

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接