SQL Where Clause with Values Provided - java

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.

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.

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

Can you use a PreparedStatement?

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

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

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.

Related

Getting an error in createStatement

When I use the following code it runs perfectly.
PreparedStatement st = con.prepareStatement("select * from users where username=?");
st.setString(1, userId);
ResultSet rs = st.executeQuery();
But when I am using the following code, I get an error that userId (that I pass as parameter) is an invalid column name.
Statement st = con.createStatement();
ResultSet rs = st.executeQuery("select * from users where username="+userId);
Why statement method doesn't work and I have to use PreparedStatement?
User ID is a string (SQL calls this type CHAR or VARCHAR), it must be put in quotes if used in the SQL requests. Like this:
select * from users where username='12345'
PreparedStatement is much better solution because of the SQL injection. You CANNOT just write:
ResultSet rs = st.executeQuery("select * from users where username=\""+userId+"\"");
WRONG CODE - ^^^^^^^^^^^^^^^
because user ID can contains control characters like ['], ["] or [\]. It depends on the SQL server and sometimes are more sophisticated than it looks like. If using PreparedStatement, it is automatically managed by the JDBC driver.
First of all, is better to use the first one. But if you really want to use the second one, you need to put your value into quotes. Simple add the quotes to the value. But is good to create a function to it, if you are going to use it a loot. Like:
public String doubleQuoted(String value){
return "\"" + value + "\"";
}
or
public String singleQuoted(String value){
return "'" + value + "'";
}
and use
ResultSet rs = st.executeQuery("select * from users where username="+singleQuoted(userId));
You need to put strings into quotes:
Statement st = con.createStatement();
ResultSet rs = st.executeQuery("select * from users where username=\'"+userId+"\'");
\ is the escape character.
Note:
Your prepared statement is the preferred way of handling SQL queries. See #30thh answer as to why (SQL Injection attacks).

How to use the "WHERE LIKE" command in SQL

I am trying to use the WHERE LIKE command in my program.
My Code
String searchCriteria = searchTextField.getText();
String searchCriteria1 ="'"+"%" + searchCriteria + "%"+"'";\
String query = "select ID,Priority,recipient,Sender,Label,Subject from Messages where Message like = '" + searchCriteria1 + "'";
PreparedStatement pst = connection.prepareStatement(query);
ResultSet rs = pst.executeQuery();
table.setModel(DbUtils.resultSetToTableModel(rs));
Code Explained
1.What this code codes is get the input from the user.
2.Creates a string variable that contains the search condition and the "%" either side of the condition.
3.The last few lines execute the SQL query.
I am currently getting the error java.sql.SQLSyntaxErrorException: Syntax error: Encountered "=" at line 1, column 92. and not sure whats wrong with my statement.
Its most likely to be something very silly and small, I hope you can help.
Thank you
Seems as if you have single quotes twice over in the search criteria.
But you need to use prepared statement with bind parameters in this case.
You should use PreparedStatement like this:
String searchCriteria = searchTextField.getText();
String query = "select ID,Priority,recipient,Sender,Label,Subject from Messages where Message like ?";
PreparedStatement pst = connection.prepareStatement(query);
pst.setString(1, "%" + searchCriteria + "%");
ResultSet rs = pst.executeQuery();
Instead of putting your modulus(%) in your variable you can put it at the query itself and remove your equal(=) symbol. See below:
String searchCriteria1 =" + searchCriteria + ";
String query = "SELECT ID,Priority,recipient,Sender,Label,Subject FROM Messages WHERE Message LIKE '%" + searchCriteria1 + "%'";

Wrong SQL in Java

I am trying to run a SQL statement in Java and I am getting syntax
String number,key; //populate number and key.
rs = stmt.executeQuery("select count(*)
from users_transition
where phoneNumber =" +number +"and randKey="+key);
In MySQL database, phoneNumber is BigInt(20) and key is Int(11).
Also, according to this link. The table 5.1 says that types in MYSQl can be converted to what types in Java. Doesnt the other way round would work too?
Here's the ERROR
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'randKey=9999' at line 1
You are missing a space between the number and the AND operator:
rs = stmt.executeQuery("select count(*) from users_transition where phoneNumber =" +number +" and randKey="+key);
// ^
You should replace the query with prepared statement, and use query parameters. This would help you not only avoid simple errors like this, but also make your code immune to SQL injection attacks.
String sql = "select count(*) from users_transition where phoneNumber =? and randKey=?";
PreparedStatement getCount = con.prepareStatement(sql);
getCount.setBigDecimal(1, new BigDecimal(number));
getCount.setBigDecimal(2, new BigDecimal(randKey));
I'll tell you what is wrong, and then I'll tell you what is very wrong.
What is wrong
First, you are building a query which where has missing spaces (and possibly missing quotes):
String number,key; //populate number and key.
rs = stmt.executeQuery("select count(*) "
+ "from users_transition "
+ "where phoneNumber =" +number +" and randKey="+key)";
// ^ you missed a space here
What is very wrong
Your query is vulnerable to SQL Injection Attacks (please read the link, it provides a humorous example and tips on solving the problem). Use prepared statements to do this kind of thing:
String number, key;
PreparedStatement ps = conn.prepareStatement("select count(*) "
+ "from users_transition "
+ "where phoneNumber=? "
+ " and randKey=?");
// The question marks are place holders for values
// You can assign this values with setXXX() methods
ps.setString(1, number);
ps.setString(2, randKey);
ResultSet rs = ps.executeQuery();
// Do whatever you need to do with the ResultSet

Get the data from mysql rows and display them separately by the ResultSet in Java

I have a mysql table user which is consisted of id, name, password and email columns.
Is there a way to create some sort of query or java code that will print in my message dialog window all of the users names.
try{
Class.forName("com.mysql.jdbc.Driver").newInstance();
Connection con = DriverManager.getConnection("jdbc:mysql://localhost/mydb","root","");
String sql = "select * from user;";
Statement st = con.createStatement();
ResultSet rs = st.executeQuery(sql);
if (rs.next()) {
val1 = rs.getString(2);
val2 = rs.getString(3);
}
value = val1 + " " + val2;
JOptionPane.showMessageDialog(null,value);
}catch(SQLException e){
JOptionPane.showMessageDialog(null, e);
}
}
This only prints the name and the surname of the first user from the table :(
I want to print them all one below another!
If I set rs.getString(5); - it gives me an error: column index out of range.
I suggest you avoid JOptionPane for this kind of code. Better to use some Frame (Swing) and display all of the users into a separate window.
The problem with your code is that variable value is lyiong outside of the loop (which must be btw while loop, as spencer said).
try{
Class.forName("com.mysql.jdbc.Driver").newInstance();
Connection con = DriverManager.getConnection("jdbc:mysql://localhost/mydb","root","");
String sql = "select * from user;";
Statement st = con.createStatement();
ResultSet rs = st.executeQuery(sql);
while (rs.next()) {
val = rs.getString(2) + " " + rs.getString(3);
value += val + " ";
}
JOptionPane.showMessageDialog(null,value);
}catch(SQLException e){
JOptionPane.showMessageDialog(null, e);
}
}
Try to avoid this type of code, use ArrayList and save in the array all of the users credentials. Then easily label it wherever you want.
You're only fetching the first row from the resultset. It sounds like you want a loop, and process every row from the resultset.
while (rs.next()) {
}
UPDATE
Q: It only gives me now the last user. Probably because it overwrites the val1 and val2 variable. I suppose somehow this should also goes into the loop..
A: Yes, it should go inside the loop. But I'd be populating a collection, rather than concatenating a String.
As a performance and maintenance note, you can avoid the messiness of the string concatenation in the Java by doing the concatenation in the SQL statement. I wouldn't use SELECT * and rely on the positions of two particular columns in the resultset.
I'd use a SQL statement like this:
SELECT CONCAT(u.first_name,' ',u.last_name) AS user_name FROM users
If I wasn't populating a collection, and I needed to concatenate a honkous string, I'd use a StringBuffer, e.g.
val = new StringBuffer(4096));
while (rs.next()) {
val.append(rs.getString("user_name"));
}
value = val.toString;

Prepared statement - using a function as part of the where clause

I am working with a Java prepared statement that gets data from an Oracle database. Due to some performance problems, the query uses a "virtual column" as an index.
The query looks like this:
String status = "processed";
String customerId = 123;
String query = "SELECT DISTINCT trans_id FROM trans WHERE status = " + status + " AND FN_GET_CUST_ID(trans.trans_id) = " + customerId;
Connection conn = getConnection();
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = conn.prepareStatement(query);
ps.execute();
...
} catch (...)
This does not work. Having the function as part of the where clause causes a SQLException. I am aware of CallableStatement, and know I could use that first and then concatenate the results. However, this table uses FN_GET_CUST_ID(trans_id) as part of it's index. Is there a way to use a prepared statement with a database function as a query parameter?
Never concatenate arguments for the SQL into the String. Always use placeholders (?) and setXxx(column, value);.
You'll get the same error if you'd run the SQL in a your favorite DB tool. The problem is that Oracle can't use the function for some reason. What error code do you get?
If Customer ID is numeric keep in int not in String. Then try doing the following:
String query = "SELECT DISTINCT trans_id FROM trans WHERE status = ? AND FN_GET_CUST_ID(trans.trans_id) = ?";
ps = conn.prepareStatement(query);
ps.setString(1, status);
ps.setInt(2, customerId);
ps.execute();
Besides other benefits of prepared statement you won't have to remember about string quotations (this causes your error most likely) and escaping of the special characters.
At the first glance, the query seems to be incorrect. You are missing an apostrophe before and after the usage of status variable (assuming that status is a varchar column).
String query = "SELECT DISTINCT trans_id FROM trans
WHERE status = '" + status + "' AND FN_GET_CUST_ID(trans.trans_id) = " + customerId;
EDIT: I am not from java background. However, as #Aron has said, it is better to use placeholders & then use some method to set values for parameters to avoid SQL Injection.

Categories