sql >> Base de Datos >  >> RDS >> Mysql

Nombre de columna dinámica usando declaración preparada + consulta sql con variable que contiene 's

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).