JSP PreparedStatement Error with Setting ? in SQL query - sql

I have below a segment of the code I have. Please see:
Workload workload;
ArrayList<Workload> workList = null;
System.out.print("first");
try{
System.out.print("first");
ConnectionFactory myFactory = ConnectionFactory.getFactory();
Connection conn = myFactory.getConnection();
int i = 0;
PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM WORKLOAD WHERE datestart LIKE '? %'");
PreparedStatement pstmtMember = conn.prepareStatement("SELECT * FROM MEMBER WHERE memberid = ? and deletestatus = 0");
PreparedStatement pstmtLeader = conn.prepareStatement("SELECT * FROM LEADER WHERE leaderid = ? and deletestatus = 0");
pstmt.setString(i++, startdate);
ResultSet rs = pstmt.executeQuery();
workList = new ArrayList<Workload>();
My problem with the code is that it "goes out" once it reaches the pstmt.setString part.
The reason why i put a LIKE '? %' is because I needed to get only the date in from the query. Not the whole time stamp. Basically it disregards what comes after putting a date like '2012-04-05'.

You can't put the single quotes around it like that you can only treat the ? like it was a variable written in a procedure
Like '#yourVar %'
That is the equivalent of what you wrote.
The following will only work if the date is stored in a character field
String startDateWithPercent = startdate + " %"
PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM WORKLOAD WHERE datestart LIKE ?");
pstmt.setString(i++, startDateWithPercent);
If the datatype on datestart in the database is datetime you will need to do something like this respective to your database platform (this is sql server). Only replacing that individual prepareStatement line.
PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM WORKLOAD WHERE CONVERT(datestart,DATE) LIKE ?");

Related

Breaking up a static string sql command into the command portion and seperate parameters

I have a static string with parameters, being sent to an SQL Execute command.
The strings have the format of delete 'Name' from table where x = 1 and y = 2 or select * from table where x = 1 and y = 2.
My problem is that I need to break the string into parameters.
How do I break the strings so that I can pass the command with the parameters to a single functional with the least possible work?
I have only one function to fix and handle this problem.
From this:
protected object ExecuteScaler(string queryString)
{ OpenConnection(); }
DbCommand command = _provider.CreateCommand();
command.Connection = _connection; command.CommandText = queryString; command.CommandType = CommandType.Text; if (_useTransaction) {
command.Transaction = _transaction; }
try { returnValue = command.ExecuteScalar(); } ...
Can someone please give me an example?
When you build a sql-command like this:
// don't do this because of sql injection
sql = "SELECT * FROM MyTable WHERE Col2 = " + somevalue;
Where you "break out of" the string constant to place a value, that is the point where you want to use a parameter placeholder:
// safe from sql injection
sql = "SELECT * FROM MyTable WHERE Col2 = #somevalue";
And then you can supply the value for #somevalue using the Parameters collection.
When the query needs some fixed values, then it is probably OK to keep them in the string:
// the "type" never changes for this query:
sql = "SELECT * FROM MyTable WHERE type=1 and Col2 = #somevalue";

Hibernate complains about double single quote

I am trying to select some data using Hibernate
The query ends up as follows
"select mystuff from mytable where upper(mystuff)=upper('a''c')"
( a'c is comming from user input escaped by StringEscapeUtils.escapeSql())
Hibernate is giving me a SQLGrammarException. Did I escape that single quote wrong?
I think '' to escape ' is good. I suppose that Hibernate + some RDBMS can have some mistakes with those quotes escaping. You should try to use preparedStatement or Query interface of Hibernate. To inject you data with method like this :
String selectSQL = "select mystuff from mytable where upper(mystuff)=upper(?)";
PreparedStatement preparedStatement = dbConnection.prepareStatement(selectSQL);
preparedStatement.setString(1, "a'c");
ResultSet rs = preparedStatement.executeQuery(selectSQL);
while (rs.next()) {
String mystuff = rs.getString("mystuff");
}
Or like this :
Query query = session.createQuery("from mytable where upper(mystuff)=upper(:mystuff)");
query.setString("mystuff", "a'c");
List<?> list = query.list();
So hibernate will be able to handle it.
Hope it helps :)

Is there any advantage to PreparedStatement#setInt vs inline SQL?

I've read Give me Parameterized SQL or give me death numerous times.
The advantage of Parameterized SQL for Strings, Dates, and floating-point numbers is very obvious and indisputable.
My question is: what about ints?
I ask because, oftentimes, if I'm writing a query or update and the only parameter is an int, I'll just write an inline sql and append the int as a shortcut ("select * from table where id = " + id).
My question: Are there any advantages to using Parameterized SQL for ints alone?
To illustrate with Java:
Are there any advantage to this:
Connection conn;
int id;
String sql = "select * from table where id = ?";
try (PreparedStatement p_stmt = conn.prepareStatement(sql)) {
p_stmt.setInt(1, id);
ResultSet results = p_stmt.executeQuery();
// ...
} catch (SQLException e) {
// ...
}
over this:
Connection conn;
int id;
String sql = "select * from table where id = " + id;
try (Statement stmt = conn.createStatement()) {
ResultSet results = stmt.executeQuery(sql);
// ...
} catch (SQLException e) {
// ...
}
I would say the biggest advantage would be consistency. If you decide that all SQL built by string concatenation is "wrong", it's easier to verify that your code is "right", compared to a rule like "All SQL built by string concatenation is wrong, except that which deals with ints as parameters".
Another case, say: down the line, you want to introduce sorting or grouping to the query, suddenly, your line turns into something like this:
String sql = "select * from table where id = " + id + " order by somecolumn";
And hopefully you remembered the space before order. And that everyone after you does also.
There is much to be said for doing things only one way, especially when that one way is the right thing most of the time.

JDBC returns an empty result set

ResultSet is empty although query should return whole table. Here is my code
try{
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
con = DriverManager.getConnection("jdbc:sqlserver://localhost","somonjon","sa");
con.setCatalog("ChatDBS");
Statement stmt = null;
String SQL = "SELECT * FROM Login_chat";
stmt = con.createStatement();
try{
System.out.println("trying execute query");
rs = stmt.executeQuery(SQL);
}
catch(SQLException ex){
ex.printStackTrace();
}
this is the error message:
trying execute query
com.microsoft.sqlserver.jdbc.SQLServerException: The result set has no current row.
P.S.
Okey guys I'm not sure is it important or not, but this codes is jButton1ActionPerformed event.
AFAIK, you are not suppose to get this exception unless you are doing some operation over ResultSet like rs.next();
Regarding the problem is concerned, there could be two scenarios
You are not pointing to right database (catalog)
You have not committed the transaction in the database.
You have to loop through rs.
String column1;
int column2;
while (rs.next()) {
column1 = rs.getString("nameColumn1");
column2 = rs.getInt("nameColumn2");
}
Ok, in
String SQL = "SELECT * FROM Login_chat";
You have to add a ";".
String SQL = "SELECT * FROM Login_chat;";
Try with that!

JavaDB anonymous column name

I am trying to create a generalized UPDATE-statement like this, where only the table-name is fixed.
updateValueQuery = conn.prepareStatement("UPDATE TABLENAME SET (?)=(?)");
That fails with an SQLException complaining about syntax. As soon as I specify the column-name like this:
updateValueQuery = conn.prepareStatement("UPDATE TABLENAME SET COL_NAME=(?)");
SQL happily compiles. Is there any way to make the columnname anonymous as well?
I am using Apache derby.
No, PreparedStatement has holders for values only.
I resolved similar problem in following way:
private final String FIND_STRING = "select * from TABLENANE where {0} = ?";
.
.
.
private final Map<String, PreparedStatement> statements = new HashMap<String, PreparedStatement>();
private PreparedStatement prepareStatement(String field, String toFind) throws SQLException{
PreparedStatement statement = null;
if (statements.contains(field)){
statement = statements.get(field);
}else{
String findInHelpDefinition = MessageFormat.format(FIND_STRING, field));
statement = connection.prepareStatement(findInHelpDefinition);
statemnts.put(field, statement);
}
statement.setString(1, toFind);
return statement;
}