I want to write a mysql select query using preparedstatement. But theres syntax error at the last part which is concat('%', itemName, '%')"; itemName is a column of table ItemMain.
I already tried 3 queries given below.
String sql ="SELECT * FROM ItemMain WHERE ? = 'All' OR ? like concat('%', itemName, '%')";
String sql ="SELECT * FROM ItemMain WHERE ? = 'All' OR ? like '%'+itemName+'%'";
String sql ="SELECT * FROM ItemMain WHERE ? = 'All' OR ? like '%itemName%'";
You can't use placeholders for field names. The queries would have to be
... WHERE somefield=? OR otherfield LIKE concat('%', ?, '%')
placeholders are for VALUES only. field/table names, function namesm or any of the "Structural" words in SQL are offlimits.
This is a general rule for mysql prepared statements. It is not a java/php/c#/whatever restriction.
Although #Marc B is absolutely right (+1) I would like to add something. I believe that your have a real task where you need such functionality, so I would like to suggest you the following solution.
You can create query dynamically as following. If you are using plain JDBC you can run query like desc YOUR_TABLE_NAME. It will return a easy-to-parse list of fields in your table. You can implement your "like" statement yourself either using regular expression or simple string manipulation methods as startsWith("xyz") instead of like 'xyz%', endsWith("xyz") instead of like '%xyz' and contains("xyz") instead of like '%xyz%'. Now you can create SQL statement dynamically by adding fields the meet your requirements.
Found the answer to my problem.
String sql ="SELECT * FROM ItemMain WHERE ? = 'All' OR itemName like '%"+keyword+"%'";
Object []values ={keyword};
ResultSet res = DBHandller.getData(sql, conn, values);
I swapped the column name, keyword and change the syntax here '%"+keyword+"%'";
Now it works fine. thnx al
Related
I am currently working on fixing some SQL injection bugs in my project.
Here is my current sql string:
String sql = "select * from :table order by storenum";
Here is how I am setting the parameters:
SQLQuery query = sess.createSQLQuery(sql).setParameter("table", table);
(table is a string that is passed in through a method)
Whenever I run the program I get something like this:
select * from ? order by storenum
You can't dynamically bind table names, only values, so you'll have to resort to string manipulation/concatenation to get the table name dynamically. However, you would probably want to escape it to avoid SQL Injections.
I'm having issues dealing with the single quote while using it in a prepared statement in JAVA via Oracle JDBC.
Let's say we have a table Restaurant with a column restaurant_name with 1 value : Jack's Deli
I want to use a simple prepared statement query like this:
String result = "Jack\'\'s Deli"
String sqlStatement = "select * from Restaurant where restauraunt_name like ? escape '\\' ";
PreparedStatement pStmt = conn.prepareStatement(sqlStatement);
pstmt.setString(1, result);
The result shows 0 returned values, however when I directly search the query in the database (ORACLE) it works fine and retrieves the result. (Oracle uses two single quotes as an escape for the first)
I am thinking that the value is not being passed properly to the database. Or there is some other formatting issue.
The point of prepared statements is that you don't need any escaping.
.setString(1, "Jack's Deli") will get it done.
I got the following error while testing some code:
SQLException: Invalid column index
What exactly does that mean?
Is there an online document explaining what all the Oracle error codes and statements?
If that's a SQLException thrown by Java, it's most likely because you are trying to get or set a value from a ResultSet, but the index you are using isn't within the range.
For example, you might be trying to get the column at index 3 from the result set, but you only have two columns being returned from the SQL query.
It sounds like you're trying to SELECT a column that doesn't exist.
Perhaps you're trying to ORDER BY a column that doesn't exist?
Any typos in your SQL statement?
Using Spring's SimpleJdbcTemplate, I got it when I tried to do this:
String sqlString = "select pwy_code from approver where university_id = '123'";
List<Map<String, Object>> rows = getSimpleJdbcTemplate().queryForList(sqlString, uniId);
I had an argument to queryForList that didn't correspond to a question mark in the SQL. The first line should have been:
String sqlString = "select pwy_code from approver where university_id = ?";
I also got this type error, problem is wrong usage of parameters to statement like, Let's say you have a query like this
SELECT * FROM EMPLOYE E WHERE E.ID = ?
and for the preparedStatement object (JDBC) if you set the parameters like
preparedStatement.setXXX(1,value);
preparedStatement.setXXX(2,value)
then it results in SQLException: Invalid column index
So, I removed that second parameter setting to prepared statement then problem solved
Just try this fix, as I faced your error:
Remove the single quotation marks around your question mark, which means, if you used your reserved parameters like ('?','?','?') you should make it look like this:
(?,?,?)
I had this problem using a prepared statement. I didn't add enough "?" for the "VALUES" My eclipse had crashed after I did add the proper amount, and lost those changes. But that didn't occur to me to be the error until I started combing through the SQL as p.campbell suggested.
I had the exact same problem when using Spring Security 3.1.0. and Oracle 11G. I was using the following query and getting the invalid column index error:
<security:jdbc-user-service data-source-ref="dataSource"
users-by-username-query="SELECT A.user_name AS username, A.password AS password FROM MB_REG_USER A where A.user_name=lower(?)"
It turns out that I needed to add: "1 as enabled" to the query:
<security:jdbc-user-service data-source-ref="dataSource" users-by-username query="SELECT A.user_name AS username, A.password AS password, 1 as enabled FROM MB_REG_USER A where A.user_name=lower(?)"
Everything worked after that. I believe this could be a bug in the Spring JDBC core package...
the final sql statement is something like:
select col_1 from table_X where col_2 = 'abcd';
i run this inside my SQL IDE and everything is ok.
Next, i try to build this statement with java:
String queryString= "select col_1 from table_X where col_2 = '?';";
PreparedStatement stmt = con.prepareStatement(queryString);
stmt.setString(1, "abcd"); //raises java.sql.SQLException: Invalid column index
Although the sql statement (the first one, ran against the database) contains quotes around string values, and also finishes with a semicolumn, the string that i pass to the PreparedStatement should not contain quotes around the wildcard character ?, nor should it finish with semicolumn.
i just removed the characters that appear on white background
"select col_1 from table_X where col_2 = ' ? ' ; ";
to obtain
"select col_1 from table_X where col_2 = ?";
(i found the solution here: https://coderanch.com/t/424689/databases/java-sql-SQLException-Invalid-column)
I had this problem in one legacy application that create prepared statement dynamically.
String firstName;
StringBuilder query =new StringBuilder("select id, name from employee where country_Code=1");
query.append("and name like '");
query.append(firstName + "' ");
query.append("and ssn=?");
PreparedStatement preparedStatement =new prepareStatement(query.toString());
when it try to set value for ssn, it was giving invalid column index error, and finally found out that it is caused by firstName having ' within; that disturb the syntax.
I got the following error while testing some code:
SQLException: Invalid column index
What exactly does that mean?
Is there an online document explaining what all the Oracle error codes and statements?
If that's a SQLException thrown by Java, it's most likely because you are trying to get or set a value from a ResultSet, but the index you are using isn't within the range.
For example, you might be trying to get the column at index 3 from the result set, but you only have two columns being returned from the SQL query.
It sounds like you're trying to SELECT a column that doesn't exist.
Perhaps you're trying to ORDER BY a column that doesn't exist?
Any typos in your SQL statement?
Using Spring's SimpleJdbcTemplate, I got it when I tried to do this:
String sqlString = "select pwy_code from approver where university_id = '123'";
List<Map<String, Object>> rows = getSimpleJdbcTemplate().queryForList(sqlString, uniId);
I had an argument to queryForList that didn't correspond to a question mark in the SQL. The first line should have been:
String sqlString = "select pwy_code from approver where university_id = ?";
I also got this type error, problem is wrong usage of parameters to statement like, Let's say you have a query like this
SELECT * FROM EMPLOYE E WHERE E.ID = ?
and for the preparedStatement object (JDBC) if you set the parameters like
preparedStatement.setXXX(1,value);
preparedStatement.setXXX(2,value)
then it results in SQLException: Invalid column index
So, I removed that second parameter setting to prepared statement then problem solved
Just try this fix, as I faced your error:
Remove the single quotation marks around your question mark, which means, if you used your reserved parameters like ('?','?','?') you should make it look like this:
(?,?,?)
I had this problem using a prepared statement. I didn't add enough "?" for the "VALUES" My eclipse had crashed after I did add the proper amount, and lost those changes. But that didn't occur to me to be the error until I started combing through the SQL as p.campbell suggested.
I had the exact same problem when using Spring Security 3.1.0. and Oracle 11G. I was using the following query and getting the invalid column index error:
<security:jdbc-user-service data-source-ref="dataSource"
users-by-username-query="SELECT A.user_name AS username, A.password AS password FROM MB_REG_USER A where A.user_name=lower(?)"
It turns out that I needed to add: "1 as enabled" to the query:
<security:jdbc-user-service data-source-ref="dataSource" users-by-username query="SELECT A.user_name AS username, A.password AS password, 1 as enabled FROM MB_REG_USER A where A.user_name=lower(?)"
Everything worked after that. I believe this could be a bug in the Spring JDBC core package...
the final sql statement is something like:
select col_1 from table_X where col_2 = 'abcd';
i run this inside my SQL IDE and everything is ok.
Next, i try to build this statement with java:
String queryString= "select col_1 from table_X where col_2 = '?';";
PreparedStatement stmt = con.prepareStatement(queryString);
stmt.setString(1, "abcd"); //raises java.sql.SQLException: Invalid column index
Although the sql statement (the first one, ran against the database) contains quotes around string values, and also finishes with a semicolumn, the string that i pass to the PreparedStatement should not contain quotes around the wildcard character ?, nor should it finish with semicolumn.
i just removed the characters that appear on white background
"select col_1 from table_X where col_2 = ' ? ' ; ";
to obtain
"select col_1 from table_X where col_2 = ?";
(i found the solution here: https://coderanch.com/t/424689/databases/java-sql-SQLException-Invalid-column)
I had this problem in one legacy application that create prepared statement dynamically.
String firstName;
StringBuilder query =new StringBuilder("select id, name from employee where country_Code=1");
query.append("and name like '");
query.append(firstName + "' ");
query.append("and ssn=?");
PreparedStatement preparedStatement =new prepareStatement(query.toString());
when it try to set value for ssn, it was giving invalid column index error, and finally found out that it is caused by firstName having ' within; that disturb the syntax.
For some sql statements I can't use a prepared statment, for instance:
SELECT MAX(AGE) FROM ?
For instance when I want to vary the table. Is there a utility that sanitizes sql in Java? There is one in ruby.
Right, prepared statement query parameters can be used only where you would use a single literal value. You can't use a parameter for a table name, a column name, a list of values, or any other SQL syntax.
So you have to interpolate your application variable into the SQL string and quote the string appropriately. Do use quoting to delimit your table name identifier, and escape the quote string by doubling it:
java.sql.DatabaseMetaData md = conn.getMetaData();
String q = md.getIdentifierQuoteString();
String sql = "SELECT MAX(AGE) FROM %s%s%s";
sql = String.format(sql, q, tablename.replaceAll(q, q+q), q);
For example, if your table name is literally table"name, and your RDBMS identifier quote character is ", then sql should contain a string like:
SELECT MAX(AGE) FROM "table""name"
I also agree with #ChssPly76's comment -- it's best if your user input is actually not the literal table name, but a signifier that your code maps into a table name, which you then interpolate into the SQL query. This gives you more assurance that no SQL injection can occur.
HashMap h = new HashMap<String,String>();
/* user-friendly table name maps to actual, ugly table name */
h.put("accounts", "tbl_accounts123");
userTablename = ... /* user input */
if (h.containsKey(userTablename)) {
tablename = h.get(userTablename);
} else {
throw ... /* Exception that user input is invalid */
}
String sql = "SELECT MAX(AGE) FROM %s";
/* we know the table names are safe because we wrote them */
sql = String.format(sql, tablename);
Not possible. Best what you can do is to use String#format().
String sql = "SELECT MAX(AGE) FROM %s";
sql = String.format(sql, tablename);
Note that this doesn't avoid SQL injection risks. If the tablename is a user/client-controlled value, you'd need to sanitize it using String#replaceAll().
tablename = tablename.replaceAll("[^\\w]", "");
Hope this helps.
[Edit] I should add: do NOT use this for column values where you can use PreparedStatement for. Just continue using it the usual way for any column values.
[Edit2] Best would be to not let the user/client be able to enter the tablename the way it want, but better present a dropdown containing all valid tablenames (which you can obtain by DatabaseMetaData#getCatalogs()) in the UI so that the user/client can select it. Don't forget to check in the server side if the selection is valid because one could spoof the request parameters.
In this case you could validate the table name against the list of available tables, by getting the table listing from the DatabaseMetaData. In reality it would probably just be easier to use a regex to strip spaces, perhaps also some sql reserved words, ";", etc from the string prior to using something liek String.format to build your complete sql statement.
The reason you can't use preparedStatement is because it is probably encasing the table name in ''s and escaping it like a string.