2016-02-02 22 views
36

Sto cercando di creare un'istruzione SQL utilizzando i dati forniti dall'utente. Io uso il codice simile a questo:Come posso aggiungere un input fornito dall'utente a un'istruzione SQL?

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

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

Tuttavia,

  • questo viene a mancare quando l'input dell'utente contiene virgolette singole (ad esempio O'Brien),
  • io non riesco a ottenere il giusto formato quando si inserisce DateTime valori e
  • le persone continuano a dirmi che non dovrei farlo a causa di "SQL injection".

Come si fa "nel modo giusto"?

+5

Nota: Questa domanda è da intendersi come una domanda canonica per le persone che non possono ottenere i loro SQLs stringa-concatenato al lavoro. [Se vuoi discuterne, ecco la meta domanda corrispondente.] (Http://meta.stackoverflow.com/q/315913/87698) – Heinzi

+2

Se desideri uno sguardo più approfondito su cosa sia "SQL Injection" e perché è pericoloso vedere la domanda: "[Come posso spiegare l'SQL injection senza gergo tecnico?] (http://security.stackexchange.com/questions/25684/how-can-i-explain-sql-injection-without- tecnico-gergo tecnico) "dal nostro sito gemello sulla sicurezza delle informazioni. –

+1

Si dovrebbe wiki questo, btw. – Will

risposta

42

Utilizzare l'SQL parametrizzato.

Esempi

sostituire il vostro concatenazioni di stringhe con @... segnaposto e, successivamente, aggiungere i valori al vostro SqlCommand. Puoi scegliere liberamente il nome dei segnaposto, ma assicurati che inizi con il segno @. Il vostro esempio sarà simile a questa:

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(); 
} 

Lo stesso modello viene utilizzato per altri tipi di istruzioni SQL:

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

// see above, same as INSERT 

o

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

Una parola di cautela: AddWithValue è una buona punto di partenza e funziona bene nella maggior parte dei casi. Tuttavia, è necessario che il valore che si trasmette corrisponda esattamente al tipo di dati del campo del database corrispondente. In caso contrario, si potrebbe finire in una situazione in cui la conversione impedisce la query da using an index. Si noti che alcuni tipi di dati di SQL Server, come char/varchar (senza precedente "n") o data, non hanno un tipo di dati .NET corrispondente. In questi casi, Add with the correct data type should be used instead.

Perché dovrei farlo?

Altre librerie di accesso ai database

+0

Attento con la dichiarazione "altro tipo" - SELECT non funzionerà con 'cmd.ExecuteNonQuery()' – Hogan

+0

@Hogan: True. Ho pensato di dare un esempio più completo, ma poiché questa risposta riguarda principalmente la transizione da SQL concatenato da stringhe a SQL parametrizzato, non volevo gonfiare la risposta aggiungendo troppo codice che "non cambierà" (se fosse ExecuteScalar prima, è ExecuteScalar in seguito). – Heinzi

+0

@Heinze - Penso che mi piacerebbe un breve punto elenco in casi speciali che dicesse qualcosa come "l'uso dei parametri funzionerà anche se si sta eseguendo 'ExecuteQuery(), ExecuteReader(), ExecuteScalar()' o altri .. – Hogan