"Escape" Bind Variable ? in JDBC SQL search - java

So I am coding in Java, using JDBC with SQL to get data from a database. I cannot chnage the data or the column names in the database. Everything worked perfectly until I was told today that another column of the database was needed.
So I tried to add the column name to the select statement, however I get an error:
"java.sql.SQLException: [Microsoft][ODBC Microsoft Access Driver] Too few parameters. Expected 2."
Here is the variable and name for the column: String est = "\"Estimates Complete?\"";
So after LOTS of research, it seems that there is something called "Bind Variables" in JDBC and ? happens to be one of them. I keep finding forum posts and answers on how to create Bind Variables, but nothing on how to "Escape" them. I cannot change the value of the Estimates Complete? column, and it is needed for my program.
If I try String est = "Estimates Complete?";, then the error I get is:
java.sql.SQLException: [Microsoft][ODBC Microsoft Access Driver]COUNT field incorrect
Anyone know if it is possible? Thanks.
Edit: Code example:
Statement s = conn.createStatement();
String tableName = "\"Open WRs V2\"", data1 = "\"Project Name\"",est = "Estimates Complete?";
String selTable = "SELECT " + data1 + "," + est+ " FROM " + tableName;
s.execute(selTable);
ResultSet rs = s.getResultSet();
while ((rs.next())) {
String name = (rs.getString(1));
String estimate= rs.getString(2);
System.out.println("test: "+estmate);
}
s.close();

can you replace the ? with chr(63) like in the answer here :
How to avoid ODBC parameterization for the question mark character ? within literals and comments?

Related

How do PostgreeSQL functions return multiple columns and rows to a Java application?

I am trying to get 3 fields from 1 table using a function and I am getting errors:
CREATE OR REPLACE FUNCTION sp_search_test_ui_test_prog_revision(dev TEXT)
RETURNS table (dev_op_test_id BIGINT, test_program_name TEXT, test_program_revision TEXT)
AS $$
BEGIN
RETURN QUERY
SELECT dev_op_test_id, test_program_name, test_program_revision
FROM dev_op_test
WHERE device = dev
ORDER BY dev_op_test_id;
END;
$$ LANGUAGE plpgsql;
The JAVA code is below: (device is a String passed to this method) Is this where the error is?
// Get unique devices from dev_op_test
String sql = " SELECT sp_search_test_ui_test_prog_revision(" + device + ") ";
PreparedStatement statement = pgConn.prepareStatement(sql);
ResultSet rs = statement.executeQuery();
// Clear from previous run
cboTestProgDev.getItems().clear();
while (rs.next()) {
TestProgRev tpr = new TestProgRev();
tpr.setDevOpTestId(rs.getLong(1));
tpr.setTestProgramName(rs.getString(2));
tpr.setTestProgramRevision(rs.getString(3));
testProgs.add(tpr);
cboTestProgDev.getItems().add(tpr.toString());
}
And this is the error I keep getting. Notice it's telling me the column doesn't exist, which is true because that is a value not a column name. Any ideas??? I know it may be something simple, I just can't seem to ding the anwser.
The query you are sending is
SELECT sp_search_test_ui_test_prog_revision(mnf0306aa)
Do you notice the missing single quotes around the string? That is why PostgreSQL interprets it as a column name and complains that the column does not exist.
Composing queries with string concatenation is dangerous, it exposes you to the dangers of SQL injection. If device contains a single quote, your statement would cause an error or worse – a skilled attacker could do anything with your database.
Use the power of prepared statements to avoid that danger:
java.sql.PreparedStatement statement =
pgConn.prepareStatement("SELECT * FROM sp_search_test_ui_test_prog_revision(?)";
statement.setString(1, device);
java.sql.ResultSet rs = statement.executeQuery();

Update table using 2 columns in Java

Hi there i have this code which is having an error when i try to run it.
s.executeUpdate("UPDATE [salesRecord] SET [backOrder] = 'backOrder'," +
" [quantity] ='"+ conDiff +"'" +
"WHERE [productID] = '" + s1 +"' AND [orderNumber] = '"+valueOrder+"' " );
the purpose of this code is to set orders as back orders when all items are not delivered. i want to specify which product i will update by setting my where to look for that item using productID and orderNumber.
java.sql.SQLException: [Microsoft][ODBC Microsoft Access Driver]
Too few parameters. Expected 1.
at sun.jdbc.odbc.JdbcOdbc.createSQLException(Unknown Source)
Above is the error that shows when i try to run the program.
Try the following
Let backOrder , conDiff , s1, valueOrder be the variables.
s.executeUpdate("UPDATE [salesRecord] SET [backOrder] = '"+backOrder+"',[quantity] ='"+ conDiff +"' WHERE [productID] = '" + s1 +"' AND [orderNumber] = '"+valueOrder+"' " );
The query you have written is not using any parameters, but the error message says it is expecting one. This means that your "s" is probably being reused from somewhere else before and, that is using a parameter.
Seeing as you are using Java, I assume s is a java.sql.PreparedStatement or similar and that a parameter has been set using any one of the s.setXXX(parameterIndex, value) methods.
more details see http://docs.oracle.com/javase/7/docs/api/index.html
The simple solution is to use new statement.

Error in SQL update query in JDBC

For the command given below, if the variable body_template contains " Abhinav's number", it shows the following 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 's number
String sql_command = "Update email_template set body_template='"+body_template+"' WHERE id="+idno;
//body_template, idno are of type String
stmt.executeUpdate(sql_command); //Here stmt is a variable of type statement.
Kindly suggest how should I redesign my query so as to handle such cases. Note: Input can't be changed. The problem is coming due to the inclusion of ' in the input.
Note: Input can't be changed. The problem is coming due to the inclusion of ' in the input.
Best practice is to use PreparedStatement for binding the input values with the query parameters. It manages to escape special characters if any in the input values.
Example:
// body_template, idno are of type String
String sql_command = "Update email_template set body_template=? WHERE id=?";
PreparedStatement pst = con.prepareStatement( sql_command );
pst.setString( 1, body_template );
pst.setString( 2, idno );
int updateResult = pst.executeUpdate();
String sql_command = "Update email_template set body_template=\""+body_template+"\" WHERE id="+idno;
//body_template, idno are of type String
stmt.executeUpdate(sql_command); //Here stmt is a variable of type statement.
if body_template doesn't contain ", then this code would work. obviously if body_template does have it then you run into same problem as before. just make sure body_template only contains one type of quotes

Java adding data to table using SQL

I am using an sql query to add data data to an existing database table.
I want to add data under the columns 'Room_Resource' and 'Quantity'.
The system is designed to allow bookings and i am trying to add bookings made to a tblBookings table, the code below is taken from JButton clicked function.
The value I want to add to Room_Resource is a name taken from a selected table within the system. I declared a variable for this 'resourceChosenString'
The value I want to add to quantity is from the 'Quantity' variable i have declared in relation to a combo box.
Here are my declarations:
int selectedResourceRow = tblResources.getSelectedRow();
Object resourceChosen = tblResources.getValueAt(selectedResourceRow,1);
String resourceChosenString = resourceChosen.toString();
int Quantity = cmbQuantity.getSelectedIndex();
I then have a sql statement:
String sql = ("INSERT INTO tblBookings (Room_Resource,Quantity) VALUES (" + resourceChosenString + " ', ' " + Quantity + " ',) ");
And then the execute code:
try{
pst = conn.prepareStatement(sql);
pst.execute();
JOptionPane.showMessageDialog(null, "Added");
} catch (Exception e){
JOptionPane.showMessageDialog(null, "Error Adding Booking");
}
Currently it gives me an error when I attempt to add the data to the table and wondered if anyone had any suggestions?
Also I considered that perhaps the problem could lie in the fact I have more than two columns in the external table and the table I am adding the data to so columns could be left blank. If this could be the problem, could anyone tell me how to get around it? Possibly if there is a null function I can use instead of values.
You probably want to tell us what database you're using and what error message you're getting. But just off the bat, it looks like your sql string is not formatted correctly. I don't know if you mistyped it in the question or if your code has a simple syntax error.
Just shooting from the hip with what you have, it looks like your sql statement should be:
String sql = "INSERT INTO tblBookings (Room_Resource,Quantity) VALUES ('" + resourceChosenString + "', " + Quantity + ")";
Notice that resourceChosenString should be wrapped in single quotes (you're missing the single quote on the left). Also, I don't think you're supposed to wrap a number in single quotes (I could be wrong since I don't know which database you're using).
Qwerky is right though; you should use a PreparedStatement.
The SQL you are generating is not valid and looks like this;
INSERT INTO tblBookings (Room_Resource,Quantity) VALUES (resource ', ' 1 ',)
^ ^
missing quote extraneous comma
You should tidy it up, or better still use a PreparedStatement.
String sql = "insert into tblBookings (Room_Resource,Quantity) values (?, ?)";
PreparedStatement pst = conn.prepareStatement(sql);
pst.setString(1, resourceChosenString);
pst.setInt(2, quantity); //variable names are not capitalised by convention
pst.execute();

Why would a PreparedStatement with no input parameters succeed, but an identical version WITH input parameters fail?

I'm running the following code:
// Query without parameters
String query = "select data_source from Qc_data_blending_sources where external_object_type_name='well' AND instance_surrogate_key='837410' and attribute_name='preferred_latitude'";
PreparedStatement testPstmt = con.prepareStatement(query);
ResultSet testRs = testPstmt.executeQuery();
if(testRs.next()){
System.out.println("Result: " + testRs.getString(1));
}
// Query with parameters
sources_query = new StringBuilder("select data_source from Qc_data_blending_sources where external_object_type_name=? AND instance_surrogate_key=? AND attribute_name=?");
sourcesPstmt = con.prepareStatement(sources_query.toString());
sourcesPstmt.setString(1, vo.getWellSurrogateKey()); //set to 837410
sourcesPstmt.setString(2, "well");
sourcesPstmt.setString(3, "preferred_latitude");
dataBlendingSources.append("Preferred latitude: ");
sourcesRs = sourcesPstmt.executeQuery();
if(sourcesRs.next()){
dataBlendingSources.append(sourcesRs.getString(1) + " \n");
}
else{
dataBlendingSources.append(" not found, \n");
System.out.println("Preferred latitude not found. Query: " +
sources_query.toString() +
" \ninstance_surrogate_key: " + vo.getWellSurrogateKey() +
" attribute_name: preferred_latitude");
}
When I run it, it gives a valid result for the first query and says "preferred latitude not found" for the second one. What gives? What could be going on here?
Looks like you are using setString() entirely, but you may need to use setInt() if the column type is not a string for the surrogate key, for example.
Per prepared statement documentation:
Note: The setter methods (setShort, setString, and so on) for setting
IN parameter values must specify types that are compatible with the
defined SQL type of the input parameter. For instance, if the IN
parameter has SQL type INTEGER, then the method setInt should be
used.
Totally off the wall guess (I could be sure if I wrote code to test it, but I'm too lazy):
You call con.prepareStatement() twice on the same connection. I suggest closing the first prepareStatement before getting another prepareStatement from the database. they may be interfering with each other. I would also consider closing the resultSet too when I'm done with it.
coding suggestion: If you aren't already doing so, I suggest closing a connection, preparedStatement, and resultSet in the finally block of a try/catch/finally, in the reverse order you obtain them (checking for null before closing each).

Categories