0

I am trying to use a SQL Select statement for a query in Java. I currently have the following:

ResultSet rs = stmt.executeQuery("SELECT *" +
                                             " FROM " + table + 
                                             " WHERE " + selection + 
                                             " VALUES " + selectionArgs);

where "selection" is a string and "selectionArgs" is a string array.

 String selection = "documentFK=?";
 String[] selectionArgs = { ... };

Is it possible to use the VALUES command to replace the ? like in with the INSERT command? Either way, what would be the correct syntax?

Thanks for the help.

jdisaac
  • 25
  • 1
  • 7
  • 6
    Can you say [SQL Injection](http://en.wikipedia.org/wiki/SQL_injection) 5 times quickly? – Oded Jan 09 '12 at 19:59
  • Also: http://www.sommarskog.se/dynamic_sql.html – Oded Jan 09 '12 at 20:00
  • 1
    Off topic, but why append a string to a string? "SELECT " + "*" + can just be "SELECT *" – Johnie Karr Jan 09 '12 at 20:01
  • 1
    @Oded Yes, but can you say Sequester Cool SQL Quills five times quickly? – Nick Vaccaro Jan 09 '12 at 20:02
  • Are you trying to `INSERT` using a `SELECT` statement? Sounds like it. – Bhesh Gurung Jan 09 '12 at 20:02
  • 1
    You can not use `values` in a query. See Norla's answer for a reasonable solution. Also, as stated previously, read about SQL Injection and how to avoid it. We like to call him "little Bobby tables" http://xkcd.com/327/ – DwB Jan 09 '12 at 20:07
  • what is it really that you're trying to do? everyone else seem to interpret this question differently from me. is the amount of strings in array `selectionsArgs` always the same as the amount of question marks in the string `selection`? i mean, are the strings in `selectionArgs` supposed to replace one question mark each? – davogotland Jan 09 '12 at 20:22
  • In most cases `selectionArgs` is the same length as the number of question marks in `selection`. The original code, except for the query statement, was what already existed, and I have been porting it from Android sqlite to java sqlite jdbc. – jdisaac Jan 09 '12 at 20:27
  • @JoshIsaacson in most cases? i don't understand... are the strings in `selectionArgs` supposed to replace one question mark from `selection` each? or are you trying to find rows where the column from `selection` has one of the values from `selectionArgs`? or are you trying to do something completely different? – davogotland Jan 09 '12 at 20:33
  • @davogotland: Sorry for the miscommunication... `selectionArgs` IS the same size as the number of question marks in `selection` in EVERY case. To answer your question, I am trying to find the rows where the column from `selection` has the corresponding value from `selectionArgs`, which seems to fit the description of a `PreparedStatement` as answered below. – jdisaac Jan 09 '12 at 20:42
  • http://stackoverflow.com/questions/178479/preparedstatement-in-clause-alternatives – Chris Mazzola Jan 09 '12 at 21:55

6 Answers6

3

I believe what you're looking for is the IN statement. Your query should look like this:

SELECT *
FROM table
WHERE documentFK IN ('doc1', 'doc2', 'doc3')
    AND userFK IN ('user1', 'user2', 'user3')

This is (obviously) going to make your code a bit more ugly. You'll have to ensure that the WHERE keyword is used for the first clause, but the AND keyword is used for every other clause. Also, each list will have to be comma-delimited.

Nick Vaccaro
  • 5,428
  • 6
  • 38
  • 60
2

no, that is not the way it's done. first you create the statement from the query, using the question marks as place holders for the real values you want to put there. then you bind these values to the statement.

//the query
String sql = "SELECT " + "*" +
                " FROM " + table + 
                " WHERE documetFK = ?";

//create the statement
PreparedStatement stmt = connection.prepareStatement(sql);

//bind the value
stmt.setInt(1, 4); //1 is "the first question mark", 4 is some fk

//execute the query and get the result set back
ResultSet rs = stmt.executeQuery();

now, if you want this thing with selection string and some args, then you're going to have a loop in your java code. not sure what your array looks like (you're not giving me that much to go on), but if it's made up from strings, it would be something like this:

//the query
String sql = "SELECT " + "*" +
                " FROM " + table + 
                " WHERE " + selection;

//create the statement
PreparedStatement stmt = connection.prepareStatement(sql);

//bind the values
for(int i = 0; i < selectionArgs.length; i++) {
    stmt.setString(i, selectionArgs[i]); //i is "the nth question mark"
}

//execute the query and get the result set back
ResultSet rs = stmt.executeQuery();
davogotland
  • 2,718
  • 1
  • 15
  • 19
1

Can you use a PreparedStatement?

Bhesh Gurung
  • 50,430
  • 22
  • 93
  • 142
1

First of all SELECT .. WHERE .. VALUES is incorrect SQL syntax. Lose the VALUES part.

Then you're looking for prepared statements.

In your example it's going to look something like this:

String sql = "SELECT * FROM myTable WHERE documentFK=?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "myDocumentFK"); // parameters start from 1, not 0. also we're assuming the parameter type is String;
ResultSet rs = pstmt.executeQuery();

Or with multiple parameters:

String sql = "SELECT * FROM myTable WHERE documentFK=? AND indexTerm=?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "myDocumentFK"); // parameters start from 1, not 0. also we're assuming the parameter type is String;
pstsm.setInt(2, 100); // assume indexTerm can be 100 and is an integer
ResultSet rs = pstmt.executeQuery();

However, all of this doesn't worth your while since you can simply do the same by concatenating the value into the statement. But be aware of the SQL injections, so don't forget to escape the parameters that you're passing into the database.

PS: I was typing this way too long. You already have the answers :-)

Community
  • 1
  • 1
maksimov
  • 5,792
  • 1
  • 30
  • 38
  • please don't encourage the use of concatenated sql queries D: – davogotland Jan 09 '12 at 20:18
  • I actually use Prepared Statements somewhere else with `INSERT`. I guess I didn't think about that when doing the query. Are there any other ways to guard against SQL injections in this instance besides a Prepared Statement and escaping the parameters? – jdisaac Jan 09 '12 at 20:23
  • @davogotland I don't really encourage. I simply state what every developer has to know, and I think the drawbacks were made clear as well. – maksimov Jan 09 '12 at 20:28
  • 1
    @JoshIsaacson all user input must be sanitised one way or another. Effectively it is all about escaping, since the purpose of injections is in breaking the SQL in such a way so that it executes more than intended by the developer or - on the way back to client - contains more than the developer intended it to contain (like `` tags). – maksimov Jan 09 '12 at 20:33
0

As a side note, you may want to take a look at this to prevent SQL injections:

https://www.owasp.org/index.php/Preventing_SQL_Injection_in_Java

Luc Laverdure
  • 1,398
  • 2
  • 19
  • 36
0

Sormula can select using "IN" operator from a java.util.Collection of arbitrary size. You write no SQL. It builds the SQL SELECT query with correct number of "?" parameters. See example 4.

Jeff Miller
  • 1,424
  • 1
  • 10
  • 19