Escaping a single quote when using JdbcTemplate - java

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("'", "''");
}

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

Error In JDBC Template Querying

I am trying to write this query in order to authenticate the username and password of my API but I am getting error column not found. Both username and passwords are strings and I am using MYSQL database. I think there is a error with quotations as username and password are strings. How can I rectify the below code or is there a better way to write the same.
P.S - I am using spring MVC and this is my first project.
#Override
public TypeInfo getRole(final TypeInfo typeinfo) {
String sql =
"select Role from registartion where UserName=\"" + typeinfo.getUserName() + "and Password=\"" + typeinfo.getPassword() + "/"";
return jdbcTemplate.query(sql, new ResultSetExtractor<TypeInfo>() {
#Override
public TypeInfo extractData(ResultSet rs)
throws SQLException, DataAccessException {
if (rs.next()) {
System.out.println("VALID USER");
TypeInfo typeinfo1 = new TypeInfo();
typeinfo1.setUserName(typeinfo.getUserName());
typeinfo1.setPassword(typeinfo.getPassword());
typeinfo1.setRole(rs.getString("Role"));
return typeinfo1;
}
System.out.println("Not A valid user");
return null;
}
});
}
I am getting a error that "select Role from registartion where UserName=******" column name ******* not found.
That's not the way you should write your query.
JdbcTemplate uses an Object[] array as parameters, to avoid SQL injection.
code it somewhere in the lines of this:
String user = "yourUser";
String password = "yourPassword";
final String sql = "SELECT * from FOO where username = ? and password = ?";
Object[] sqlParameters = new Object[]{user, password};
List<YourEntityClass> list = getJdbcTemplate.query(sql, new BeanPropertyRowMapper<Your Entity Class>(YourEntityClass.class), sqlParameters);
BeanPropertyRowMapper actually maps the values for you. just make sure your entity class has the same property names as the ones on your database
more info here:
jdbcTemplate examples
The proper solution would be to use a PreparedStatement, in order to avoid having to mess with quoting and enhance security.
If you really must construct the statement by string concatination, you should note that string literals in SQL are denoted by single quotes ('), not double quotes ("):
String sql =
"select Role from registartion where UserName='" + typeinfo.getUserName() + "' and Password='" + typeinfo.getPassword() + '";
Try this.
String sql = "select Role from registartion where UserName='" + typeinfo.getUserName() + "' and Password='" + typeinfo.getPassword() + "'";
Change the double quotes (including the escape characters) to single quotes.
Close the single quote enclosing the user name (typeinfo.getUserName()). You need to keep a space between the closing single quote and the subsequent string.
If it still does not work then check the table names and column names. Maybe it is 'registration' and not 'registartion'? Or may be it is 'user_name' and not 'username'?
Tips for beginners: Copy paste the sql string into any database browser, replace the variables with actual values and execute. Check for any errors. It is easier to fix errors this way.
And lastly, use parameterized sql queries to avoid sql injection. In my opinion parameterized queries reduces syntax errors too.
You have to use single qoutes around the column values:
"select Role from registartion where UserName='" + typeinfo.getUserName() + "' and Password='" + typeinfo.getPassword() + "'";
You should better use PreparedStatement. It is easier to read and safer (prevents sql injection).

How to Alter table using JOOQ?

Previously I was working with statement but I need to convert it with JOOQ
Statement dboSt = null;
dboSt = dboConn.createStatement();
I need to know how to change my below lines in JOOQ.
dboSt.executeUpdate("alter login \"" + UserId + "\" with password='" + NewPassword + "'");
dboSt.executeUpdate("alter login \"" + UserId + "\" with password='" + NewPassword + "' old_password='" + OldPassword
+ "'");
Is there any solution to convert it?
jOOQ doesn't support typesafe DDL (yet). It's been on the roadmap for a while: #883
In the mean time, you can execute plain SQL statements using jOOQ directly, as such:
DSLContext ctx = DSL.using(configuration);
// As before, manually inlining arguments:
ctx.execute("alter login \""+UserId+"\" with password='"+NewPassword+"'");
// Better, letting jOOQ do the string escaping for you, preventing
// syntax errors and SQL injection vulnerabilities:
ctx.execute("alter login {0} with password = {1}",
DSL.name(UserId), // org.jooq.Name is rendered with quotes in most DBs
DSL.inline(NewPassword) // org.jooq.Param is inlined as a (string) literal
);

Insert into database a scraped page containing double quotes with MySQL and Java

Imagine my page has a bunch of sections looking something like this (example page):
<div class="content">
</div>
My goal is to scrape the entire page into a MySQL DB entry. I currently do this like so:
//Declare SQL statement
String sql = "INSERT into rns " +
"(rns_pub_date, rns_headline, rns_link, rns_fulltext, constituent_id) values (\""+
rns.getRnsPubDate() + "\",\"" +
rns.getRnsHeadline() + "\",\"" +
rns.getRnsLink() + "\",\"" +
rns.getRnsFullText() + "\",\"" +
"(select constituent_id from constituent where constituent_name = " + rns.getRnsConstituentName() + "\")";
//SQL Statement Debug
Log.d(CLASS_NAME, "createRns. sqlStatement: " + sql);
//Initialize insertValues
insertValues = connect.prepareStatement(sql);
However, this falls over because there are multiple " marks in the page.
I can see a few options:
Escape the characters like this: '\"'
Replace the characters with: '"'
Remove all non-relevant data (the HTML) and save only the relevant data to the DB
I realise that there's also best practice with regards to preventing SQL injection. However this is a standalone system, so for the moment isn't an issue. Having said that if any answer can explain how to prevent that, I would prefer to implement that instead.
Edit 1:
Following on from #chrylis comment. This is what I have:
//Insert values into variables
String rns_pub_date = rns.getRnsPubDate();
String rns_headline = rns.getRnsHeadline();
String rns_link = rns.getRnsLink();
String rns_fulltext = rns.getRnsFullText();
String rns_constituent_name = rns.getRnsConstituentName();
//Prepare the SQL string
String sql = "INSERT into rns (rns_pub_date, rns_headline, rns_link, rns_fulltext,constituent_id) VALUES" + "(?,?,?,?,(select constituent_id from constituent where constituent_name = \"" + rns.getRnsConstituentName() + "\")";
//Prepare the statement
PreparedStatement prest = connect.prepareStatement(sql);
prest.setString(1, rns_pub_date);
prest.setString(2, rns_headline);
prest.setString(3, rns_link);
prest.setString(4, rns_fulltext);
prest.setString(5, rns_constituent_name);
However it provides this error:
Parameter index out of range (5 > number of parameters, which is 4).
Edit 2:
The insert was fixed by removing the escaped double quotes for the 5th parameter:
String sql = "INSERT into rns (rns_pub_date, rns_headline, rns_link, rns_fulltext, constituent_id) VALUES" + "(?,?,?,?,(select constituent_id from constituent where constituent_name = ?))";
Use PreparedStatement, there will be no need for escaping. Usage example is in API
It's not only a bad practice because of SQL injection, it's slow and inefficient, too, and has problems with quote characters. Use a parameterized query.

SQL error Too few parameters

I'm having an sql problem. I writing a java application on top of a Access database.
It's a search query for several fields and I know the error is in the part where I need to calculate the age of a person when he or she went missing. I'm returning a tablemodel in my method so i need to do the calculations in my query. My latest atempt to make it work is this:
public TableModel UpdateTable(String dossiernr, String naam, String voornaam,
String startleeftijd, String eindleeftijd, String dossierjaar, String geslacht)
{
TableModel tb = null;
String sql= "SELECT [Nr dossier],[Annee],[Nom],[Prenom],[Disparu le],[Ne le],[Sexe], DATEDIFF('yyyy',[Ne le],[Disparu le]) - iif(DATEADD('yyyy', DATEDIFF('yyyy',[Ne le],[Disparu le]),"
+ "[Ne le])>[Disparu le],1,0) AS Age FROM TotalTable "
+ "WHERE [Nr dossier] LIKE ? AND [Nom] LIKE ? AND [Prenom] LIKE ? AND [Annee] LIKE ? AND Age >= ? AND Age <= ? AND [Sexe] LIKE ?;";
try
{
PreparedStatement pstatement;
Connection connection = PersistentieController.getInstance().getConnection();
pstatement = initStatement(connection,sql);
pstatement.setString(1, "%" + dossiernr + "%");
pstatement.setString(2, "%" + naam + "%");
pstatement.setString(3, "%" + voornaam + "%");
pstatement.setString(4, "%" + dossierjaar + "%");
pstatement.setString(5, startleeftijd);
pstatement.setString(6, eindleeftijd);
pstatement.setString(7, "%" + geslacht + "%");
rs=pstatement.executeQuery();
tb = DbUtils.resultSetToTableModel(rs);
pstatement.close();
}//einde try
catch (SQLException e)
{
e.printStackTrace();
} //einde catch
return tb;
}
When i run it, i get following error:
java.sql.SQLException: [Microsoft][ODBC Microsoft Access Driver] Too few parameters. Expected 8.
I only work with 7 parameters and don't get why he's asking for 8.
Thanks
You count 7 parameters in your WHERE clause. Unfortunately, the Access db engine treats Age as another parameter in that situation, so it thinks you have 8 parameters instead of only 7.
To understand why, start with this query which runs without error with my Access database:
SELECT some_text AS foo
FROM tblFoo
WHERE some_text Is Not Null;
However, when attempting to use the alias instead of the field name in the WHERE clause, Access prompts me to supply a value for foo because it treats it as a parameter:
SELECT some_text AS foo
FROM tblFoo
WHERE foo Is Not Null;
Access limits your ability to re-use alias names later in a query. In certain cases, it will accept the alias, but yours is not one of those cases.
You could define the alias in a subquery. Then the db engine will recognize it correctly when you reference the subquery's alias in the parent query.
If possible, test your SQL statements directly in Access. If they fail, that effort will give you the best chance to determine why.

Categories

Resources