How to use SQL Wildcard in PreparedStatement with variable - java

On my web site, I need to perform a wild card query with a value provided by the end user. The best practice is to use a PreparedStatement mainly to avoid SQL Injection. My query is very very long so this is an example:
String query = "SELECT ... FROM ... WHERE ..."+ //
"AND UPPER(CUST_NAME) LIKE UPPER('%?%')";
PreparedStatement pstmt = conn.prepareStatement(query);
stmt.setString(1, "joe");
The problem is the setString() throws an exception: SQL Exception: Invalid column index

Instead of using the concat operator you could use
like upper('%' || ? || '%')
slightly more readable.

Try:
String query = "SELECT ... FROM ... WHERE ..."+ //
"AND UPPER(CUST_NAME) LIKE UPPER(?)";
PreparedStatement pstmt = conn.prepareStatement(query);
stmt.setString(1, "%joe%");

Replace...
UPPER('%?%')
...with...
UPPER(?)
...then set the parameter value as:
pstmt.setString(1, "%joe%");
BTW this query has a potential for poor performance. For good performance you'll need a functional index on UPPER(CUST_NAME) ("normal" index on CUST_NAME is not enough) and you'll need to only query by prefix (e.g. "joe%"). Querying by suffix (such as "%joe" or "%joe%") cannot be sped-up by an index.

Related

SQL query for updating column with values from a local variable

How can I update my SQL Table column with the value that is stored in a local variable.
In my program I have taken value from the HTML page using the following statement:
String idd=request.getParameter("id");
String report=request.getParameter("rprt");
So now I have to update the value of report in my database table named "ptest" and I am using the following query:
Class.forName("com.mysql.jdbc.Driver");
java.sql.Connection con =
DriverManager.getConnection("jdbc:mysql://localhost:3306/tcs","root","root");
Statement st= con.createStatement();
ResultSet rs;
int i=st.executeUpdate("update ptest set result = #reprt where patient_id=
#idd");
out.println("Successfully Entered");
But the value is not being stored in the database instead NULL is being stored.
I have already seen this question and got no help.
Question
Please ignore my mistakes if any in this question as I am new to MYSQL.
You can use prepared statements in java.
setString or setInt can set different data types into your prepared statements.
The parameter 1, 2 are basically the positions of the question mark. setString(1,report) means that it would set the string report in the 1st question mark in your query.
Hope this code helps you in achieving what you want.
String query = "update ptest set result = ? where patient_id = ?";
PreparedStatement preparedStatement = con.prepareStatement(query);
preparedStatement.setString(1, report);
preparedStatement.setString(2, idd);
preparedStatement.executeUpdate();
In JDBC, you use ? as placeholders for where you want to inject values into a statement.
So you should do something like this ...
Class.forName("com.mysql.jdbc.Driver");
java.sql.Connection con =
DriverManager.getConnection("jdbc:mysql://localhost:3306/tcs","root","root");
PreparedStatement st= con.prepareCall("update ptest set result = ? where patient_id=
?");
///now set the params in order
st.setString(1, report);
st.setString(2, idd);
//then execute
st.executeUpdate();
Doing a string concat with the values is dangerous due to sql injection possibilities, so I typically make statement text static and final, and also if your value has a ' in it that could blow up your sql syntax etc. Also, notice the use of executeUpdate rather than query.
Hope this helps

How to pass JSP parameters to a SQL query?

I want to write a SQL query which contains parameters from a JSP.
I tried it like this
String sqlstring = "\"select"+Activity+" from backgroundcost where onpremprice =' "
+service+" '\"";
PreparedStatement ps = con.prepareStatement(sqlstring);
ResultSet rs = ps.executeQuery();
I'm getting an error.
First of all, I hope you mean that service is a variable that comes from a form of your JSP, that this variable ends up in your Controller and that your controller delegates the access to the database layer to another class.
There are multiple problems with your request :
You use quotes inside your SQL query, you shouldn't.
What is Activity ? probably you miss a space character between ´select´ and the value of `Activity´
The goal of a ´PreparedStatement` is to avoid SQL Injection. You MUST use the code i show below instead of your parameter directly injected in your built SQL statement.
Consider using StringBuilderif you have multiple String concatenations
"
String sqlstring = "select activity from backgroundcost where onpremprice = ?";
PreparedStatement ps = con.prepareStatement(sqlstring);
ps.setString(1, service);
ResultSet rs = ps.executeQuery();
Don't is the short answer. It is a bad design to have database logic in your view. Pass the params from your jsp to a backend java bean en let that fill in the query
make it like this..
String sqlstring = "select * from backgroundcost where onpremprice ='"+service+" '";
PreparedStatement ps = con.prepareStatement(sqlstring);
ResultSet rs = ps.executeQuery();
// in place of * you can put the column name that u need to be selected.

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

Oracle query inside java

String sql = "INSERT INTO Student_Info(name,roll_no,address,phone_no) VALUES('101', 1, 'Fatma', '25')";
String sql = "insert into Student_Info(name,roll_no,address,phone_no) VALUES("+student.getName()+","+student.getRoll_no()+","+student.getAddress()+","+student.getPhone_no()+")";
the last query shows an error:
java.sql.SQLException: ORA-00917: missing comma
at
statement.executeUpdate(sql);
Can anyone rule out where am I missing the comma?
You miss the single quotes around student.name, student.address and student.phone_no
String sql = "insert into Student_Info(name,roll_no,address,phone_no) VALUES('"+
student.getName()+"',"+
student.getRoll_no()+",'"+
student.getAddress()+"','"+
student.getPhone_no()+"')";
Do notice that this sql statement is vulnerable for sql injection attacks. Use a PreparedStatement.
String sql = "insert into Student_Info(name,roll_no,address,phone_no) " +
"VALUES(?,?,?,?)";
addStudent = con.prepareStatement(sql);
addStudent.setString(1, student.getName());
addStudent.setInt(2, student.getRoll_no());
addStudent.setString(3, student.getAddress());
addStudent.setString(4, student.getPhone_no());
addStudent.executeUpdate();
con.commit();
Do it in this way:
String sql = "insert into Student_Info(name, roll_no, address, phone_no)
VALUES(?, ?, ?, ?)";
PreparedStatement ps = con.prepareStatement(sql);
ps.setString(1, value); // indexing starts from 1 (not from zero)
...
ps.executeUpdate();
// commit if you have set auto-commit to false
Never use raw statements but PreparedStatements1. Raw statements have lower performance, are more vulnerable (SQL Injection attacks) and what is most important is readability of code that is on very low level (especially in case if you have more columns).
1PreparedStatements are much more safer, pre-compiled, have better performance and are user-friedly readable and more...
rene's answer is correct. I would like to add, however:
It is much better practice to use Prepared Statements
Your code would look something like:
String sql = "INSERT INTO Student_Info(?,?,?,?) VALUES(?,?,?,?)"
PreparedStatement sql_prepared = connection_object.prepareStatement(sql)

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