Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Dynamischer Spaltenname mit vorbereiteter Anweisung + SQL-Abfrage mit Variable, die 's enthält

Recht. Wir können keine Bezeichner als Bindungsparameter bereitstellen. Der Name der Spalte muss Teil des SQL-Textes sein.

Wir können den Namen der Spalte wie folgt dynamisch in den SQL-Text einbauen:

  sql = "UPDATE diseaseinfo"
      + " SET `" + colname + "` = ?"
      + " WHERE companyname = 'mycom' AND diseaseName = ?";

Und liefern Sie Werte für die beiden verbleibenden Bindungsparameter

  preparedStmt.setString(1, attrData);
  preparedStmt.setString(2, medname);

Und Sie haben absolut Recht, wenn Sie sich Sorgen über SQL Injection machen.

Als Bindungswerte geliefert, einfache Anführungszeichen in den Werten von attrData und medname wird in Bezug auf SQL Injection kein Problem sein.

Aber das Beispiel, das ich bereitgestellt habe, ist ist angreifbar durch Einbindung des colname Variable in den SQL-Text, wenn wir nicht garantiert haben, dass colname in die Aussage "sicher" aufgenommen werden kann.

Wir müssen also colname einen Wert zuweisen "sicher".

Dazu können wir mehrere Ansätze verwenden. Am sichersten wäre ein „Whitelist“-Ansatz. Der Code kann sicherstellen, dass colname nur bestimmte zulässige "sichere" Werte zugewiesen werden , vor colname wird in den SQL-Text eingefügt.

Als einfaches Beispiel:

  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 
  }

Ein flexiblerer Ansatz besteht darin sicherzustellen, dass in colname kein Backtick-Zeichen erscheint . Im Beispiel der Wert von colname wird escaped indem Sie es in Backticks einschließen. Solange also kein Backtick-Zeichen in colname vorkommt , verhindern wir, dass ein bereitgestellter Wert als etwas anderes als als eine Kennung interpretiert wird.

Für einen allgemeineren (und komplizierteren) Ansatz zur Verwendung von hartcodierten Backtick-Zeichen könnten wir die Verwendung von supportsQuotedIdentifiers in Betracht ziehen und getIdentifierQuoteString Methoden von java.sql.DatabaseMetaData Klasse.

(Im OP-Code sehen wir den Datentyp des Inhalts von attributes nicht . Wir sehen einen Aufruf einer Methode namens replace , und die Argumente, die dazu geliefert werden. Angenommen, dass attributes ein String ist, und das soll ein Spaltenname sein, ist es überhaupt nicht klar, warum wir "space single quote space" im String haben oder warum wir das entfernen müssen. Abgesehen von dieser Erwähnung geht diese Antwort darauf nicht ein.)