I have a connection with oracle like this:
Connection con=getConnection();
String query="select ?, ? from my_table";
PreparedStatement p=con.prepareStatement(query);
p.setString(1, "id");
p.setString(2, "lastName ");
ResultSet rs=p.executeQuery();
Everything is ok here but I'am wondering how doing this when you don't have a fixed number of parameters you want to select.
For example, in above, I want to select only 'id' and 'lastName'. But those parameters are taken from different Java method and depends on the situation that method can return a different number of parameters which I would like to pass to my SQL select.
I don't know the parameters in advance so once I can get only 'id' and 'lastName' but next time 'id','firstName','address' and 'city'. Then I want to pass them to SQL query.
Can anyone tell me how to use parameters in sql query in such case?
When you don't know how much parameter you required. Then make a program that accept String array/list then join them comma delimiter. This should solve your problem.
e.g.
String paramsList = new String[]{"id", "first_name", "last_name"};
If you are using Java8 you can use String.join like :
String params = String.join(",", paramsList);
Then write your sql statement like
String query="select " + params + " from my_table";
Related
I am new in the database side. My Question is, how to append a piece of query as param arguments. In my logic we are trying to append query using below
GET_DATA= "SELECT [:metrics] from table name"
am passing metrics as argument like below
paramMap.put("metrics", "name,age");
when am executing the query using query runner.
ResultSet rs = queryRunner.runQuery(context, GET_DATA, paramMap, RESULT_SET_HANDLER);
The output of the query like below
SELECT 'name,age' from table name
How can i avoid single quotes from the query?
I have tried these two changes but getting SQL error
[metrics]
metrics
If we put similar syntax with a condition like where colum_name=[:abc],its work fine for me.
Expecting a better solution.
Try this:
String columns = paramMap.get("metrics");
GET_DATA = "Select" +
columns +
" FROM" +
" name";
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'm trying to build a web page to better learn Java and SQL. My question is, is there a way in Java to make a generic SQL select statement? For example:
SELECT var1 FROM var2 WHERE var3=var4
or something of the sort.
My idea is to fill the vars with user selected items from the web page. I know this can be done in PHP using the Post method, but I'm not using PHP. Also, I've read about the Prepared Statement in Java, but seems only to work when the used after the comparison operator; ex:
SELECT * FROM table Where attr = ? &
Also, I do know i can do the hard coded version of "SELECT " + var1 + "FROM " + var2 + "WHERE attr = " + var3 + " " but that doesn't seem very generic and prone to a lot of errors.
Incase: I'm trying to build this test page using HTML & JSP.
What you are doing with the ? is parameterizing the query. The query can only be parameterized for values not names of tables or columns.
Every time you run a query. The database has to create a query plan. If you are running the same query again and again, you can reduce this overhead by creating a PreparedStatement.
The first execution of PreparedStatement will generate the query plan. The subsequent executions will reuse the same plan.
Same query here means, it is identical in all respects except values used in where clause, expressions etc.
If you change the Column or Table name or modify the structure of the query, then it is a different query and will require a different query plan. A PreparedStement is not useful in this case and you should stick to the hardcoded version you talked about. Because of this reason you will get an error if you try to parameterize Table or Column names in PreparedStement.
Having said that. It is not advisable to take such a generic approach for queries. If your queries are that simple, you can benefit from ORM tools. You would not have to maintain even a line of SQL. For complex queries you have an option of using ORM specific query language or JPQL or Native SQL. Look for JPA + Hibernate
Your specific usage is not permitted by JDBC. You need to hard code the table name when creating the prepared statement. If you really do want to do that I suggest you use String concatenation to create the SQL statements and then create a PreparedStatement with parameters to handle the where part. In case you are wondering why bother with PreparedStatements in the specific solution, it's to avoid SQL injection.
You can use PreparedStatement to achive your objective.
For example -
String query = "SELECT * FROM table Where attr = ?";
PreparedStatement pt = con.prepareStatement(query);
pt.setString(1, attribete);
pt.executeUpdate();
There is no such direct provision in any of SQL packaged classes or others to replace table, column names along with query parameter values, in a query string, using a single method.
You require to depend on both PreparedStatement and any of String methods replace(...) and replaceFirst(...) to achieve your requirement.
String sql = "Select $1, $2 from $3 where $4=? and $5=?";
sql = sql.replaceFirst( "$1", "col1_name" );
sql = sql.replaceFirst( "$2", "col2_name" );
sql = sql.replaceFirst( "$3", "table_name" );
sql = sql.replaceFirst( "$4", "col4_name" );
sql = sql.replaceFirst( "$5", "col5_name" );
// .. and so on
PreparedStatement pst = con.prepareStatement( sql );
// use relevant set methods to set the query parametrs.
pst.setXXX( 1, value_for_first_query_parameter ); // from a variable or literal
pst.setXXX( 2, value_for_second_query_parameter); // from a variable or literal
// ... and so on
If you are using JDBC, can try this
PreparedStatement statement = connection.prepareStatement("SELECT ? FROM ? WHERE ?=? ");
then
statement.setString(1, "column_name");
statement.setString(2, "table_name");
statement.setString(3, "column_name");
statement.setBigDecimal(4, 123);
If you are using other ORM like Hibernate or JPA, I believe there are also ways to do.
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.