You can't set table name in prepared statement
As said before, it is not possible to set the table name in a prepared statement with preparedStatement.setString(1, tableName)
. And it is also not possible to add parts of the SQL query to a prepared statement (eg preparedStatement.addSql(" or xyz is null")
).
How to do it right without risking SQL injections?
The table name must be inserted into the SQL (or JQL) query you want to execute with string operations like "select * from " + tableName
or String.format("select * from %s", tableName)
But how to avoid SQL injections?
If the table name does not come from user input, you are probably safe.
For example, if you make a decision like here
String tableName;
if(condition) {
tableName = "animal";
} else {
tableName = "plant";
}
final String sqlQuery = "delete from " + tableName;
...
If the table name depends on the users input, you need to check the input manually.
For example, with a white-list containing all valid table names:
if(!tableNamesWhitelist.contains(tableName)) {
throw new IllegalArgumentException(tableName + " is not a valid table name");
}
String sqlQuery = "delete from " + tableName;
or with an enum:
public enum Table {
ANIMAL("animal"),
PLANT("plant");
private sqlTableName;
private TableName(String sqlTableName) {
this.sqlTableName= sqlTableName;
}
public getSqlTableName() {
return sqlTableName;
}
}
and then convert the user-input string like ANIMAL
into Table.ANIMAL
. An exception is thrown, if no fitting enumeration value does exist.
eg
@DeleteMapping("/{table}")
public String deleteByEnum(@PathVariable("table") Table table) {
final String sqlQuery = "delete from " + table.getSqlTableName();
...
}
Of course these examples work with select, update, ... too and a lot of other implementations to check the user input are possible.