Varying content of an SQL update statement in java - java

I need to write an update function where its content is different based on what parameters are passed, e.g. if I have updateBook(int id, String title, String author, int pages), I have to do something like:
String sql;
if((!title.equals("null"))&&(!author.equals("null"))&&(pages>0)))
sql = "UPDATE book SET title='"+title+"', author='"+author+"', pages="+pages;
else if(((!title.equals("null"))&&(!author.equals("null")))
sql = "UPDATE book SET title='"+title+"', author='"+author+"'";
else if(((!title.equals("null"))&&(pages>0)))
sql = "UPDATE book SET title='"+title+"', pages="+pages;
... //and so on
sql = sql + " WHERE bookid="+id+";";
The more fields I have in my table, the more checks I have to do, which is uncomfortable, and requires me to write a lot of code.
Also, doing something like:
sql = "UPDATE book SET ";
if(!title.equals("null"))
sql = sql +"title='"+title+"',";
if(!author.equals("null"))
sql = sql+"author='"+author+"',";
if(pages>0)
sql = sql+"pages="+pages";
sql = sql + ";";
can't work since the unwanted commas cause statement errors.
You can see as well that if I have something like 6, 7, 8 etc field the checks start to get too many, and I can't also do more separated update statements as if something goes wrong I would need to rollback any query that has been done in that function.
Is there any way round to get a custom update statement having to write few code?

Firstly, use a PreparedStatement.
I would do it something like the following.
List<Object> params = new ArrayList<>();
StringBuilder sql = new StringBuilder();
if(!title.equals("null")) {
sql.append("title = ?");
params.add(title);
}
if(!author.equals("null")) {
if (sql.length() > 0) {
sql.append(", ");
}
sql.append("author = ?");
params.add(author);
}
if(pages>0) {
if (sql.length() > 0) {
sql.append(", ");
}
sql.append("pages = ?");
params.add(pages);
}
if (sql.length() > 0) {
sql.insert(0, "UPDATE book SET ");
sql.append(" WHERE bookid=?");
java.sql.Connection conn = // however you obtain it
java.sql.PreparedStatement ps = conn.prepareStatement(sql.toString());
for (int i = 0; i < params.size(); i++) {
ps.setObject(i + 1, params.get(i));
}
ps.executeUpdate();
}

Related

How can insert into a created table in JDBC after using if statement

Hi guy's I need to know how can I (insert into) a created table cause I'm getting a lot of errors :
Connection con = DriverManager.getConnection(DB_URL,username,password);
//query for the offer Validity
String query = "SELECT chargingtime,CHARGINGPARTYNUMBER,SUBSCRIBERID,OFFERNAME,OFFERID,prepaidbalance,LIFECYCLE_DAYS,LVL,OPERATIONID FROM ncs_sub_unsub";
try (Statement stmt = con.createStatement()) {
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
String SUBSCRIBERI = rs.getString("SUBSCRIBERID");
String OFFERNAME = rs.getString("OFFERNAME");
String OFFERID = rs.getString("OFFERID");
String LIFECYCLE_DAYS = rs.getString("LIFECYCLE_DAYS");
int LEVEL1 = rs.getInt("LVL");
String CHARGINGPARTY =rs.getString("CHARGINGPARTYNUMBER");
int OPERATIONID= rs.getInt("OPERATIONID");
float prepaid_balance = rs.getFloat("PREPAIDBALANCE");
LocalDate CHARGINGTIME1 = rs.getObject("CHARGINGTIME", LocalDate.class);
LocalDate CHARGINGTIME7 = CHARGINGTIME1.plusDays(7);
LocalDate CHARGINGTIME14 = CHARGINGTIME1.plusDays(14);
//if the level is one , the time should be 7 days
if(LEVEL1 == 1){
if((OPERATIONID == 4050001 && CHARGINGTIME1.isBefore(CHARGINGTIME7)) || CHARGINGTIME1.isEqual(CHARGINGTIME7)){
String q = String.valueOf(stmt.executeUpdate("INSERT INTO aggregation VALUES (SUBSCRIBERI,CHARGINGPARTY,OPERATIONID,OFFERNAME,prepaid_balance,LIFECYCLE_DAYS,LEVEL1,'S')"));
} else if ((OPERATIONID == 4050018 && CHARGINGTIME7.isAfter(CHARGINGTIME1)) || CHARGINGTIME7.isEqual(CHARGINGTIME1)) {
String q = String.valueOf(stmt.executeUpdate("INSERT INTO aggregation VALUES (SUBSCRIBERI,CHARGINGPARTY,OPERATIONID,OFFERNAME,prepaid_balance,LIFECYCLE_DAYS,LEVEL1,'U')"));
}else {
String q = String.valueOf(stmt.executeUpdate("INSERT INTO aggregation VALUES (SUBSCRIBERI,CHARGINGPARTY,OPERATIONID,OFFERNAME,prepaid_balance,LIFECYCLE_DAYS,LEVEL1,'E')"));
}
}
}
}// end of try
catch (SQLException e){
e.printStackTrace();
}
}
public static void main(String[] args) throws SQLException {
ViewTable();
}
}
The error:
Caused by: Error : 984, Position : 111, Sql = INSERT INTO aggregation VALUES (SUBSCRIBERI,CHARGINGPARTY,OPERATIONID,OFFERNAME,prepaid_balance,LIFECYCLE_DAYS,LEVEL1,'U'), OriginalSql = INSERT INTO aggregation VALUES (SUBSCRIBERI,CHARGINGPARTY,OPERATIONID,OFFERNAME,prepaid_balance,LIFECYCLE_DAYS,LEVEL1,'U'), Error Msg = ORA-00984: column not allowed here
It looks like the Insert sql query is wrong.
I think you are trying to insert String values without '' and String values into float columns.
INSERT INTO aggregation VALUES (SUBSCRIBERI,CHARGINGPARTY,OPERATIONID,OFFERNAME,prepaid_balance,LIFECYCLE_DAYS,LEVEL1,'U')
This is not a valid sql query since prepaid_balance is not a number and SUBSCRIBERI is not a string (try 'SUBSCRIBERI' etc)
stmt.executeUpdate("INSERT INTO aggregation VALUES (SUBSCRIBERI,CHARGINGPARTY,OPERATIONID,OFFERNAME,prepaid_balance,LIFECYCLE_DAYS,LEVEL1,'U')"));
This doesn't work. You can't use java variable names inside a string and expect the system to figure it out. That string is based verbatim to the SQL JDBC driver which is not capable of doing that sort of thing.
What you want is [A] not executeUpdate, it can't do this. You want prepareStatement. The statement would be something like:
"INSERT INTO aggregation VALUES (?,?,?,?,?,?,?,'U')"
and then you use the various .setX methods that PreparedStatement has to set the values: .setString(1, SUBSCRIBERI);, and so on for all the other question marks. Once you've done all that, you can run .executeUpdate() on the prepared statement object.
There are thousands of tutorials out on the web that show you how to use PreparedStatement here.

java sql update statement with user input

I have a problem updating my table from java.
i need to check colmunID(from my table PRODUCTS) = int id(given by user input) and change thats product price in table to one given by user.
PROBLEM:
static void x(int Userid, int Userprice) {
..........................................
String sql = "UPDATE Product set Price = Userprice where ID=Userid; ";
....}
I get error that i don't have column Userprice or Userid in my database. I don't know how to write this to check int User id which is given as argument in this method and not column in my database table which does not exists.
Assuming that you have both the columns with Integer datatype in DB,
String sql = "UPDATE Product set Price="+Userprice+" where ID="+Userid;
You are not passing the actual values to it and the extra ';' is not required. Also, I suggest you to prefer prepared statements, rather than above approach
While you definitely in production code want to use prepared statements to prevent sql injection, an easy fix would be the below.
String sql = String.format("UPDATE Product set Price = %d where ID=%d ",Userprice,Userid);
String wont evaluate variables in itself.
If the table for Userid does not exist in your database, you will not be able to use this in your SQL query. There are two options for you:
1. Pass the Userid and Userprice as a variables to the SQL query
String sql = "UPDATE Product set Price = " + Userprice + "where ID=" + Userid+ "; "
Or
2. Create the table in the database and join on that
String sql = "Update A Set A.Price = b.Userprice FROM Product as A INNER JOIN User as b on A.Userid = b.ID;"
PreparedStatement ps = null;
Connection con = null;
try {
con = getConnection();
String sql = "UPDATE Product set Price = ? where ID= ? ";
ps = con.prepareStatement(sql);
ps.setString(1, Userprice);
ps.setString(2, Userid);
int i = ps.executeUpdate();
if (i > 0) {
System.out.println("Product Updated");
} else {
System.out.println("Error Occured");
}
I think this is something you are looking for... The query should not contain ';' in the String for your code

MySQL syntax error using LIMIT command with Prepared Statement in Java

I am writing code in Java and I want to take every time I run this code the next line from a MySQL table.The second time I run this code is this.
String timh1 = "1";
String timh2 = "2";
PreparedStatement st = null;
String sqlGrammes = "SELECT SURNAME ,KATHGORIA, AFM , NAME FROM EMPLOYEE LIMIT ?,? ";
try {
st = connection.prepareStatement(sqlGrammes);
st.setString(1, timh1);
st.setString(2, timh2);
But it shows me this error :
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: 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 ''1','2'' at line 1
limit accepts integer parameters, so you should use ints, not Strings:
int timh1 = 1;
int timh2 = 2;
PreparedStatement st = null;
String sqlGrammes = "SELECT SURNAME ,KATHGORIA, AFM , NAME FROM EMPLOYEE LIMIT ?,? ";
try {
st = connection.prepareStatement(sqlGrammes);
st.setInt(1, timh1); // notice the setInt
st.setInt(2, timh2); // here too
I was able to do it without prepared statement
int i = 0;
int j = 1;
sql = "Select SURNAME ,KATHGORIA, AFM , NAME FROM EMPLOYEE limit "+i+ ","+j;
got first row as output.

Building a String parameter (with SQL content) from resource file for SQL PreparedStatement

I need to execute a SQL PreparedStatement in Java using jdbc.
I'm facing problems with one of the parameters because it has SQL content and also Strings from a resource file.
It looks something like this:
Required SQL:
SELECT * FROM Table T WHERE T.value = 10 AND T.display IN ('Sample1', 'Sample2')
In the above query, the Sample1 and Sample2 values must be passed through a parameter to a PreparedStatement.
PreparedStatement:
SELECT * FROM Table T WHERE T.value = 10 ?
In my application code I'm setting the parameters like:
statement.setString(1, "AND T.display IN ('Sample1', 'Sample2')");
However this is not returning the appropriate results.
Is there a better way to build this particular parameter considering it has SQL content and Strings too?
EDIT:
Sample1, Sample2 etc. are strings that are retrieved from an external file at run-time and there can be different number of these strings each time. I.e. there can be only one string Sample1 or multiple strings Sample1, Sample2, Sample3, etc..
EDIT2:
Database being used is Oracle.
The ? placeholder can only be used in a position where a value is expected in the query. Having a ? in any other position (as in your question: WHERE T.value = 10 ?) is simply a syntax error.
In other words: it is not possible to parametrize part of the query itself as you are trying to do; you can only parametrize values. If you need to add a dynamic number of parameters, you will need to construct the query dynamically by adding the required number of parameters and using setString(). For example:
StringBuilder sb = new StringBuilder(
"SELECT * FROM Table T WHERE T.value = 10 AND T.display IN (?");
// Note: intentionally starting at 1, first parameter already above
// Assuming always at least 1 parameter
while (int i = 1; i < params.length; i++) {
sb.append(", ?");
}
sb.append(')');
try (
PreparedStatement pstmt = con.prepareStatement(sb.toString())
) {
for (int i = 0; i < params.length; i++) {
pstmt.setString(i + 1, params[i]);
}
try (
ResultSet rs = pstmt.executeQuery();
) {
// Use resultset
}
}
Use this as PreparedStatement
"SELECT * FROM Table T WHERE T.value = 10 AND T.display IN (?, ?);"
and then call
statement.setString(1, "Sample1");
statement.setString(2, "Sample2");
before executing the statement.
Update:
String generateParamString(int params) {
StringBuilder sb = new StringBuilder("(");
for (int i = 1; i < params; i++) {
sb.append("?, ");
}
sb.append("?)");
return sb.toString();
}
List<String> samples = ... // your list with samples.
String stmtString = "SELECT * FROM Table T WHERE T.value = 10 AND T.display IN "
+ generateParamString(samples.size());
// generate statement with stmtString
for (int i = 0; i < samples.size(); i++) {
statement.setString(i + 1, samples.get(i));
}
// execute statement...

Prevent SQL injection from form-generated SQL - NO PreparedStmts

I have a search table where user will be able to filter results with a filter of the type:
Field [Name], Value [John], Remove
Rule
Field [Surname], Value [Blake],
Remove Rule
Field [Has Children], Value [Yes],
Remove Rule
Add Rule
So the user will be able to set an arbitrary set of filters, which will result essentially in a completely dynamic WHERE clause. In the future I will also have to implement more complicated logical expressions, like
Where (name=John OR name=Nick) AND (surname=Blake OR surname=Bourne),
Of all 10 fields the user may or may not filter by, I don't know how many and which filters the user will set. So, I cannot use a prepared statement (which assumes that at least we know the fields in the WHERE clause). This is why prepared statements are unfortunately out of the question, I have to do it with plain old, generated SQL.
What measures can I take to protect the application from SQL Injection (REGEX-wise or any other way)?
Java, untested.
List<String> clauses = new ArrayList<String>();
List<String> binds = new ArrayList<String>();
if (request.name != null) {
binds.add(request.name);
clauses.add("NAME = ?");
}
if (request.city != null) {
binds.add(request.city);
clauses.add("CITY = ?");
}
...
String whereClause = "";
for(String clause : clauses) {
if (whereClause.length() > 0) {
whereClause = whereClause + " AND ";
}
whereClause = whereClause + clause;
}
String sql = "SELECT * FROM table WHERE " + whereClause;
PreparedStatement ps = con.prepareStatment(sql);
int col = 1;
for(String bind : binds) {
ps.setString(col++, bind);
}
ResultSet rs = ps.executeQuery();
If you add arguments to prepared statements they will automatically be escaped.
conn = pool.getConnection( );
String selectStatement = "SELECT * FROM User WHERE userId = ? ";
PreparedStatement prepStmt = con.prepareStatement(selectStatement);
prepStmt.setString(1, userId);
ResultSet rs = prepStmt.executeQuery();
SQL Server: Dynamic where-clause
Build the where clause dynamically, but do it using parameter names.

Categories