Derecha. No podemos proporcionar identificadores como parámetros de vinculación. El nombre de la columna tiene que ser parte del texto SQL.
Podemos incorporar dinámicamente el nombre de la columna en el texto SQL con algo como esto:
sql = "UPDATE diseaseinfo"
+ " SET `" + colname + "` = ?"
+ " WHERE companyname = 'mycom' AND diseaseName = ?";
Y proporcione valores para los dos parámetros de vinculación restantes
preparedStmt.setString(1, attrData);
preparedStmt.setString(2, medname);
Y tiene toda la razón acerca de estar preocupado por la inyección de SQL.
Suministrado como valores de enlace, comillas simples en los valores de attrData
y medname
no será un problema, en términos de Inyección SQL.
Pero el ejemplo que he proporcionado es vulnerable al incorporar el colname
variable en el texto SQL, si no tenemos alguna garantía de que colname
es "seguro" para incluir en la declaración.
Entonces necesitamos hacer la asignación de un valor a colname
"seguro".
Varios enfoques que podemos usar hacen eso. El más seguro sería un enfoque de "lista blanca". El código puede garantizar que solo se asignen valores "seguros" permitidos específicos a colname
, antes de colname
se incluye en el texto SQL.
Como un ejemplo simple:
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
}
Un enfoque más flexible es asegurarse de que no aparezca un carácter de acento grave en colname
. En el ejemplo, el valor de colname
está siendo escapado encerrándolo en acentos graves. Entonces, siempre que no aparezca un carácter de acento grave en colname
, evitaremos que un valor proporcionado se interprete como algo que no sea un identificador.
Para un enfoque más genérico (y complicado) para usar caracteres de acento grave codificados, podríamos considerar usar supportsQuotedIdentifiers
y getIdentifierQuoteString
métodos de java.sql.DatabaseMetaData
clase.
(En el código OP, no vemos el tipo de datos del contenido de attributes
. Vemos una llamada a un método llamado replace
, y los argumentos que se proporcionan a eso. Suponiendo que attributes
es una cadena, y se supone que es un nombre de columna, no está del todo claro por qué tendríamos "espacio de comillas simples" en la cadena, o por qué necesitamos eliminar eso. Aparte de esta mención, esta respuesta no aborda eso).