简体   繁体   中英

SQL Select statement in java

I have a HashSet of strings, the size of the hashset is variable it can contain 10 strings or 10.000 it depends on the user that fills the list. Now I have to make a sql statement with the strings from the list where I get some information back from the database this is how I do it right now:

        for (Iterator<String> iter = currentStrings.iterator(); iter
                .hasNext();) {
            ResultSet rs = entPermission.sql
                    .executeQuery("select name from table join table_access "
                            + "on table_access.access_granted_to=table.id"
                            + " join table on table.id=table_access.name_id"
                            + " where table.name='"
                            + iter.next() + "'");
            while (rs.next()) {
                String informations = rs.getString("name");
                 informationList.add(informations);

            }
        }

So what I do now is send a request for the information for every single string in the HashSet so as you can understand it can take a while till I get the results of 10.000 strings. Is there a better (faster) way to go through the 10.000 strings without making a select statement for every single one of them?

您必须使用PreparedStatement构造pre-compiled sql 语句

Change your SELECT so that you query your DB only once, by expanding your strings into a IN :

String strIN="";
for(Iterator<String> iter = currentStrings.iterator(); iter.hasNext();)
{
    if(strIN!="")
        strIn+=",";
    strIN+="'"+iter.next()+"'";
}
ResultSet rs = entPermission.sql
    .executeQuery("select name from table join table_access "
                + "on table_access.access_granted_to=table.id"
                + " join table on table.id=table_access.name_id"
                + " where table.name IN ("+strIN+")");
//...

Note that, for the sake of clarity, I have used String for strIN ; if your currentStrings is very big, you might want to use a StringBuilder instead.

I would use a stored procedure in the database. I would avoid plain SQL queries in the code, if possible.

How about using UNION to combine the result sets - you can build up your statement programatically and send it once.

StringBuilder str = new StringBuilder("select name from table join table_access ");
str.append("on table_access.access_granted_to=table.id");
str.append(" join table on table.id=table_access.name_id");
str.append(" where table.name='");

StringBuilder query = new StringBuilder();


for (Iterator<String> iter = currentStrings.iterator(); iter
            .hasNext();) {
    query.append(str.toString());
    query.append(iter.next());
    query.append("'");

    if (iter.hasNext()) {
        query.append(" UNION ");
    }       
}

ResultSet rs = entPermission.sql.executeQuery(query);
while (rs.next()) {
    String informations = rs.getString("name");
    informationList.add(informations);
}

Do not attempt to put 10000 items into a constructed IN list. This will not work (SQL size limitation) and does not scale.

Instead, have a temp table with some integer column, and a colum for your 10000 values. greate a common random integer RR (or use a SEQUENCE, AUTOKEY etc.) and put all your 10000 values (names) into that table, in batched mode. Have a non-unique index on the integer column.

Then, JOIN against that table, limited by that integer RR. This way, all your SQL statements will be short, and constant (!). And the database is perfect at joining things.

Eventually (right after the operation, or once a day), remove outdated items from your temp table.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM