Dynamic column name using prepared statement + sql query with variable containing 's
Solution 1:
Right. We can't supply identifiers as bind parameters. The name of the column has to be part of the SQL text.
We can dynamically incorporate the name of the column into the SQL text with something like this:
sql = "UPDATE diseaseinfo"
+ " SET `" + colname + "` = ?"
+ " WHERE companyname = 'mycom' AND diseaseName = ?";
And supply values for the two remaining bind parameters
preparedStmt.setString(1, attrData);
preparedStmt.setString(2, medname);
And you are absolutely correct about being concerned about SQL Injection.
Supplied as bind values, single quotes in the values of attrData
and medname
won't be an issue, in terms of SQL Injection.
But the example I've provided is vulnerable through incorporating the colname
variable into the SQL text, if we don't have some guaranteed that colname
is "safe" to include in the statement.
So we need to make the assignment of a value to colname
"safe".
Several approaches we can use do that. The most secure would be a "whitelist" approach. The code can ensure that only specific allowed "safe" values get assigned to colname
, before colname
gets included into the SQL text.
As a simple example:
String colname;
if (attributes.equals("someexpectedvalue") {
colname = "columnname_to_be_used";
} else if (attributes.equals("someothervalid") {
colname = "valid_columname";
} else {
// unexpected/unsupported attributes value so
// handle condition or throw an exception
}
A more flexible approach is to ensure that a backtick character doesn't appear in colname
. In the example, the value of colname
is being escaped by enclosing it in backticks. So, as long as a backtick character doesn't appear in colname
, we will prevent a supplied value from being interpreted as anything other than as an identifier.
For a more generic (and complicated) approach to using hardcoded backtick characters, we could consider making use the supportsQuotedIdentifiers
and getIdentifierQuoteString
methods of java.sql.DatabaseMetaData
class.
(In the OP code, we don't see the datatype of contents of attributes
. We see a call to a method named replace
, and the arguments that are supplied to that. Assuming that attributes
is a String, and that's supposed to be a column name, it's not at all clear why we would have "space single quote space" in the string, or why we need to remove that. Other than this mention, this answer doesn't address that.)