Passing Oracle functions as String in Java - java

I have a query like this..
String query = "UPDATE tbl_customer_policies SET "+
"start_date = ?," +
"next_pay_date = ?,"+
"maturity_date = ?, " +
"modified_at = CURRENT_TIMESTAMP,"+
"modifier = ?, status = ? " +
"WHERE id = ?";
Now in place of the place-holder for start_date I want to pass a string like SYSDATE.
What I am doing now is setting that string in a variable called String startDate = "SYSDATE" and binding it to that place-holder. But I guess it does not seem to work. I get this exception
ORA-01858: a non-numeric character was found where a numeric was expected
I have to pass Oracle functions like that. How to achieve that?

If it will always be sysdate you don't need to parameterize it.
Set it directly in the query like this:
String query = "UPDATE tbl_customer_policies SET "+
"start_date = sysdate," + // or "start_date = ADD_MONTHS(SYSDATE, 12),"
"next_pay_date = ?,"+
"maturity_date = ?, " +
"modified_at = CURRENT_TIMESTAMP,"+
"modifier = ?, status = ? " +
"WHERE id = ?";
And set all the others parameters like you did before.

Use function TO_DATE (docs)
for example
"UPDATE tbl_customer_policies SET "+
"start_date = TO_DATE(?, 'DD-MON-RR')," +
"next_pay_date = TO_DATE(?, 'DD-MON-RR'),"+
and don't forget pass parameters in format like '27-OCT-98' in this case.
P.S.
I misunderstood the question so try to correct my answer.
The described problem is for limitations of PreparedStatement Java class.
PreparedStatement object is used for storing a reference to some precompiled (and optimized) SQL statement.
So you have to supply only values of parameters for filling them.
Functions must be evaluated before using their results and they aren't able to be placed there.
I guess you can use a workaround with Oracle Structured Types.
You can pass them as reference types with PreparedStatement's setRef() method.
Using functions can be implemented with a wrapper in constructor of object.
I didn't try it but it seems to me it is a possible solution.

Related

Mysql Update does not works with variables

basically when i try to use update with variables in java it doesnt works
ex:
String update = "UPDATE Clientes "
+ "SET Nombre ='"+nombre+"' , Apellido='"+apellido+"', Telefono ='"+telefono+"' ,Calle='"+calle+"',NumeroPuerta='"+numpuerta+"' , Localidad ='"+localidad+"' "
+ "WHERE Cedula = '"+ci+"' ";
that is the one that doesnt work but if i try the same but without variables it works
ex:
String update = "UPDATE Clientes "
+ "SET Nombre ='luciano', Apellido='smith', Telefono ='111111', Calle ='avenue', NumeroPuerta = '456', Localidad='maldonado' "
+ "WHERE Cedula = '123123' ";
thank to every one responding
First of all: never do what you try now: SET Nombre ='" + nombre + "'...
It is direct path to SQL Injection attack.
Instead use prepared statement with parameters like SET Nombre=?.
Second: only to find what's wrong with your query just use debugger or print resulting update string and find how it is different from working/hardcoded version.
Still you must switch to Prepared Statement with parameters for real code
UPD: example to start with (it is pure JDBC)
assuming you already have an java.sql.Connection ready:
String nombre = "John";
String apellido = "Doe";
String cedula = "12345";
String updQuery = "UPDATE Clientes SET Nombre = ?, Apellido=? WHERE Cedula = ?";
PreparedStatement updStmt = myConnection.prepareStatement(updQuery);
updStmt.setString(1, nombre);
updStmt.setString(2, apellido);
updStmt.setString(3, cedula);
updStmt.execute();
Two things in JDBC to remember (forever :-) ):
there is no way to define same parameter multiple times in the SQL query.
Parameters are just ? marks and indexes go in order how ? appear from begin to the end of SQL query.
parameter indexes start with 1 not 0
First of all, this kind of Sql generation will lead you to Sql injection. You should use PreparedStatement with question mark and pass variables which Java will take care about sql injection, check, sql generation

Use PreparedStatement to build a query

I was wondering if using PreparedStatement.setString() was a good idea (possible, sensible?) to dynamically build a query.
For example :
sql code:
SELECT * FROM table1 WHERE table1.category = ? ?
java code:
ps.setString(1,"category1");
ps.setString(2,"AND table1.category = 'category2'");
Also, would it be possible to do something like:
ps.setString(1,"category1");
ps.setString(2," AND table1.category = ?");
ps.setString(3,"category2");
Best regards
Unfortunately, NO.
PreparedStatements are strictly for values only. Table Names and Column Names (as well as conditions in your example) are not allowed. So the best way to do is to concatenate it with the string.
String others = " AND table1.category = ?";
String query = "SELECT * FROM table1 WHERE table1.category = ? " + others;
java code:
ps.setString(1,"category1");
ps.setString(2,"category2");
Whatever you put inside setString will go within single quotes ' ' and will not be interpreted as a query.

java - how to inject custom PreparedStatement's paramters

I am trying to implement PreparedStatement, which won't work with sql DB.
Suppose I have the following sql query:
String selectSqlQuery = "SELECT * FROM customer WHERE f1 = ? AND f2 =? AND f3 > ?";
and the following code:
//----
prest = con.prepareStatement(selectSqlQuery );
prest.setString(1, "val1");
prest.setString(2, "val2");
prest.setInt(3, 108);
ResultSet rs = prest.executeQuery();
//---
My question is how to implement setString and setInt methods for injecting params?
For now I save parameters' indexes and values into HashMap, but after it I can't make injection into sql query string.
implementation of sql's java interfaces are part of vendor specific jdbc driver. You probably just need to get the proper jdbc jar file for you database. writing implementations of such stuff is usually just needed if you intend to write your own database driver...
Since you're writing your own driver, you can play with your class a little. Let's change the approach. If you have a query like this one:
"SELECT * FROM table WHERE id = ? AND name = ?"
Replace the ? to turn it into
"SELECT * FROM table WHERE id = {0} AND name = {1}"
About your set methods, those will have to save your new parameters in an Object array, again matching against the index.
Object parameterArray = new Object[1];
public boolean setString(int paramIndex, String param) {
if(paramIndex < 0 || paramIndex > parameterArray.length)
throw new IllegalArgumentException("Can't set parameter " + paramIndex + ", The query only has " + parameterArray.length + " parameters.");
parameterArray[paramIndex - 1] = param;
}
Before executing the query, take advantage of your formatted string and set the parameters:
MessageFormat messageFormat = new MessageFormat(query);
String newQuery = messageFormat.format(parameterArray);
The format method will replace the {number} substrings for the corresponding element in the index represented by the number between brackets.

Escaping a single quote when using JdbcTemplate

We're using JdbcTemplate to modify our underlying Oracle database. We're doing this by way of the update(String sql) method.
The code looks somehow like the following:
String name = "My name's yellow";
String sql = "update FIELD set NAME = '" + name "' where ID = 10
jdbcTemplate.update(sql);
This causes the error:
java.sql.SQLException: ORA-00933: SQL command not properly ended
The problem is the unescaped ' in the name variable.
What's the most convenient and correct way to escape this character?
Use PreparedStatement. That way you nominate a placeholder and the JDBC driver will perform this correctly by sending the database the statement, plus the parameters as arguments.
String updateStatement =
"update " + dbName + ".COFFEES " +
"set TOTAL = TOTAL + ? " +
"where COF_NAME = ?";
PreparedStatement updateTotal = con.prepareStatement(updateStatement);
updateTotal.setInt(1, e.getValue().intValue());
updateTotal.setString(2, e.getKey());
The question marks in the above represent the placeholders.
Because these values get passed as parameters, you don't have problems with quoting, and it protects you against SQL injection too.
Try for name :
if ( name.contains("'") ){
name.replaceAll("'", "''");
}

How to change a value in mysql database using conditions from java code?

I'm trying to change a value Dr_status that only contain one int even 0 or 1. So if Dr_status equal to 1 change it to 0 and vice versa.
Here is the code :
String query = "Select Bluetooth_Address FROM dr";
String str = "40D32DBBE665";//in the database I have only two fields in `Bluetooth_Address` column 40D32DBBE665 and another value
String check = "";
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(query);
PreparedStatement preparedStmt= con.prepareStatement("update `dr` set `Dr_status` = '1'");
PreparedStatement preparedStmt1= con.prepareStatement("update `dr` set `Dr_status` = '0'");
dbtime = rs.getString(1);
if (dbtime.equals(str)){
check = "Select `Dr_status` From `dr` Where `Bluetooth_Address` = " + " " + str ;
if(check.equals(0)){
preparedStmt.executeUpdate();
}
if(check.equals(1)){
preparedStmt1.executeUpdate();
}
I don't know where is the problem !!! please help.
Thanks in advance.
I give +1 to the answer from #Marcelo Hernández Rishmawy. Instead of testing the condition in Java code, do the test and the update in an SQL expression that converts 0 to 1 and 1 to 0 automatically, for the rows that match your Bluetooth address condition.
I'll also give you a tip that in MySQL, 1 and 0 are integers, but they are also used for true and false. So you can use either of the following tricks to make the statement more compact:
"update `dr` set `Dr_status` = ! `Dr_status` where `Bluetooth_Address = " + str
This trick works too:
"update `dr` set `Dr_status` = 1 - `Dr_status` where `Bluetooth_Address = " + str
It's a nice way to simplify, but FWIW it's specific to MySQL, not standard SQL. Other databases brands use proper boolean values, not 1 and 0.
Re your comment: the error is not related to the solutions above, it's because you're interpolating a string of hex digits. You need to either quote the string, or better yet use a query parameter.
You should learn how to use query parameters in any case, because they're good for writing secure code to defend against SQL injection issues, and it's generally easier and more robust than trying to interpolate variables into SQL query strings.
See Using Prepared Statements at The Java Tutorials.
Use something similar to:
"update `dr` set `Dr_status` = CASE `Dr_status` WHEN '1' THEN '0' ELSE '1' END CASE Where `Bluetooth_Address` = '" + str + "'"
The line if(check.equals(0)){ is invalid. check is a String and will never equal 0

Categories

Resources