2016-02-02 13 views
36

Ich versuche, eine SQL-Anweisung mit benutzerdefinierten Daten zu erstellen. Ich verwende Code ähnlich wie diese:Wie kann ich benutzerdefinierte Eingaben zu einer SQL-Anweisung hinzufügen?

var sql = "INSERT INTO myTable (myField1, myField2) " + 
      "VALUES ('" + someVariable + "', '" + someTextBox.Text + "');"; 

var cmd = new SqlCommand(sql, myDbConnection); 
cmd.ExecuteNonQuery(); 

jedoch

  • dies fehlschlägt, wenn der Benutzereingabe einzelne Anführungszeichen (zB O'Brien) enthält,
  • ich nicht das Format richtig scheinen, zu erhalten, wenn Datetime Einfügen Werte und
  • Leute sagen mir immer wieder, dass ich das wegen "SQL-Injektion" nicht tun sollte.

Wie mache ich es "den richtigen Weg"?

+5

Hinweis: Diese Frage als kanonische Frage für Menschen gedacht, die nicht ihren String-verketteten SQLs bekommen zu arbeiten. [Wenn Sie darüber diskutieren möchten, hier ist die entsprechende Meta-Frage.] (Http://meta.stackoverflow.com/q/315913/87698) – Heinzi

+2

Wenn Sie einen genaueren Blick auf was "SQL Injection" ist und möchten Warum ist es gefährlich? Siehe die Frage: "[Wie kann ich SQL Injection ohne Fachjargon erklären?] (http://security.stackexchange.com/questions/25684/how-can-i-explain-sql-injection-without- Fachjargon) von unserer Information Security-Schwester-Website. –

+1

Sie sollten dies wiki, btw. – Will

Antwort

42

Verwenden Sie parametrisiertes SQL.

Beispiele

Zeichenfolge Verkettungen Ersetzen durch @... Platzhalter und danach, um die Werte zu Ihrem SqlCommand hinzuzufügen. Sie können den Namen der Platzhalter frei wählen, stellen Sie einfach sicher, dass sie mit dem @ Zeichen beginnen. Ihr Beispiel würde wie folgt aussehen:

var sql = "INSERT INTO myTable (myField1, myField2) " + 
      "VALUES (@someValue, @someOtherValue);"; 

using (var cmd = new SqlCommand(sql, myDbConnection)) 
{ 
    cmd.Parameters.AddWithValue("@someValue", someVariable); 
    cmd.Parameters.AddWithValue("@someOtherValue", someTextBox.Text); 
    cmd.ExecuteNonQuery(); 
} 

Das gleiche Muster für andere Arten von SQL-Anweisungen verwendet wird:

var sql = "UPDATE myTable SET myField1 = @newValue WHERE myField2 = @someValue;"; 

// see above, same as INSERT 

oder

var sql = "SELECT myField1, myField2 FROM myTable WHERE myField3 = @someValue;"; 

using (var cmd = new SqlCommand(sql, myDbConnection)) 
{ 
    cmd.Parameters.AddWithValue("@someValue", someVariable); 
    using (var reader = cmd.ExecuteReader()) 
    { 
     ... 
    } 
    // Alternatively: object result = cmd.ExecuteScalar(); 
    // if you are only interested in one value of one row. 
} 

Ein Wort der Vorsicht: AddWithValue ist ein gute Ausgangspunkt und funktioniert in den meisten Fällen gut. Der Wert, den Sie übergeben, muss jedoch genau mit dem Datentyp des entsprechenden Datenbankfelds übereinstimmen. Andernfalls könnten Sie in einer Situation landen, in der die Konvertierung die Abfrage von using an index verhindert. Beachten Sie, dass einige SQL Server-Datentypen wie char/varchar (ohne vorangestelltes "n") oder Datum keinen entsprechenden .NET-Datentyp aufweisen. In diesen Fällen Add with the correct data type should be used instead.

Warum sollte ich das tun?

  • It's more secure: Es stoppt SQL injection. (Bobby Tables won't delete your student records.)

  • Es ist einfacher: Keine Notwendigkeit, mit einfachen und doppelten Anführungszeichen zu hantieren oder die richtige Zeichenfolge Darstellung Datumsliterale nachzuschlagen.

  • Es ist stabiler: O'Brien wird nicht zum Absturz Ihrer Anwendung, nur weil er darauf besteht, seinen seltsamen Namen zu halten.

Andere Datenbankzugriff Bibliotheken

+0

Vorsicht mit der "anderen Art" Aussage - SELECT funktioniert nicht mit 'cmd.ExecuteNonQuery()' – Hogan

+0

@Hogan: True. Ich habe darüber nachgedacht, ein vollständigeres Beispiel zu geben, aber da es hauptsächlich um den Übergang von verkettetem SQL zu parametrisiertem SQL geht, wollte ich die Antwort nicht aufblähen, indem ich zu viel Code hinzufüge, der "nicht geändert" wird ExecuteScalar vorher, danach ExecuteScalar). – Heinzi

+0

@Heinze - Ich denke, ich möchte einen kurzen Aufzählungspunkt unter Sonderfällen sagen etwas wie "die Verwendung von Parametern funktioniert, auch wenn Sie 'ExecuteQuery(), ExecuteReader(), ExecuteScalar()' oder andere. – Hogan