Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Nome da coluna dinâmica usando instrução preparada + consulta sql com variável contendo 's


Direita. Não podemos fornecer identificadores como parâmetros de ligação. O nome da coluna deve fazer parte do texto SQL.

Podemos incorporar dinamicamente o nome da coluna no texto SQL com algo assim:
  sql = "UPDATE diseaseinfo"
      + " SET `" + colname + "` = ?"
      + " WHERE companyname = 'mycom' AND diseaseName = ?";

E forneça valores para os dois parâmetros de ligação restantes
  preparedStmt.setString(1, attrData);
  preparedStmt.setString(2, medname);

E você está absolutamente correto em se preocupar com SQL Injection.

Fornecido como valores de ligação, aspas simples nos valores de attrData e medname não será um problema, em termos de SQL Injection.

Mas o exemplo que forneci é vulnerável ao incorporar o colname variável no texto SQL, se não tivermos alguma garantia de que colname é "seguro" para incluir na declaração.

Então precisamos fazer a atribuição de um valor para colname "seguro".

Várias abordagens que podemos usar fazem isso. O mais seguro seria uma abordagem de "lista branca". O código pode garantir que apenas valores "seguros" permitidos específicos sejam atribuídos a colname , antes de colname é incluído no texto SQL.

Como um exemplo simples:
  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 
  }

Uma abordagem mais flexível é garantir que um caractere de backtick não apareça em colname . No exemplo, o valor de colname está sendo escapado colocando-o em backticks. Portanto, desde que um caractere de backtick não apareça em colname , impediremos que um valor fornecido seja interpretado como algo diferente de um identificador.

Para uma abordagem mais genérica (e complicada) de usar caracteres de backtick codificados, podemos considerar o uso de supportsQuotedIdentifiers e getIdentifierQuoteString métodos de java.sql.DatabaseMetaData aula.

(No código OP, não vemos o tipo de dados do conteúdo de attributes . Vemos uma chamada para um método chamado replace , e os argumentos que são fornecidos para isso. Supondo que attributes é uma String, e isso deveria ser um nome de coluna, não está claro por que teríamos "espaço de aspas simples" na string ou por que precisamos remover isso. Além dessa menção, esta resposta não aborda isso.)