How do I create a parameterized SQL query? Why Should I?
Solution 1:
The EXEC
example in the question would NOT be parameterized. You need parameterized queries (prepared statements in some circles) to prevent input like this from causing damage:
';DROP TABLE bar;--
Try putting that in your fuz
variable (or don't, if you value the bar
table). More subtle and damaging queries are possible as well.
Here's an example of how you do parameters with Sql Server:
Public Function GetBarFooByBaz(ByVal Baz As String) As String
Dim sql As String = "SELECT foo FROM bar WHERE baz= @Baz"
Using cn As New SqlConnection("Your connection string here"), _
cmd As New SqlCommand(sql, cn)
cmd.Parameters.Add("@Baz", SqlDbType.VarChar, 50).Value = Baz
Return cmd.ExecuteScalar().ToString()
End Using
End Function
Stored procedures are sometimes credited with preventing SQL injection. However, most of the time you still have to call them using query parameters or they don't help. If you use stored procedures exclusively, then you can turn off permissions for SELECT, UPDATE, ALTER, CREATE, DELETE, etc (just about everything but EXEC) for the application user account and get some protection that way.
Solution 2:
Definitely the last one, i.e.
Or do I need to do somethng more extensive ...? (Yes,
cmd.Parameters.Add()
)
Parametrized queries have two main advantages:
- Security: It is a good way to avoid SQL Injection vulnerabilities
- Performance: If you regularly invoke the same query just with different parameters a parametrized query might allow the database to cache your queries which is a considerable source of performance gain.
- Extra: You won't have to worry about date and time formatting issues in your database code. Similarly, if your code will ever run on machines with a non-English locale, you will not have problems with decimal points / decimal commas.
Solution 3:
You want to go with your last example as this is the only one that is truly parametrized. Besides security concerns (which are much more prevalent then you might think) it is best to let ADO.NET handle the parametrization as you cannot be sure if the value you are passing in requires single quotes around it or not without inspecting the Type
of each parameter.
[Edit] Here is an example:
SqlCommand command = new SqlCommand(
"select foo from bar where baz = @baz",
yourSqlConnection
);
SqlParameter parameter = new SqlParameter();
parameter.ParameterName = "@baz";
parameter.Value = "xyz";
command.Parameters.Add(parameter);
Solution 4:
Most people would do this through a server side programming language library, like PHP's PDO or Perl DBI.
For instance, in PDO:
$dbh=pdo_connect(); //you need a connection function, returns a pdo db connection
$sql='insert into squip values(null,?,?)';
$statement=$dbh->prepare($sql);
$data=array('my user supplied data','more stuff');
$statement->execute($data);
if($statement->rowCount()==1){/*it worked*/}
This takes care of escaping your data for database insertion.
One advantage is that you can repeat an insert many times with one prepared statement, gaining a speed advantage.
For instance, in the above query I could prepare the statement once, and then loop over creating the data array from a bunch of data and repeat the ->execute as many times as needed.
Solution 5:
Your command text need to be like:
cmdText = "SELECT foo FROM bar WHERE baz = ?"
cmdText = "EXEC foo_from_baz ?"
Then add parameter values. This way ensures that the value con only end up being used as a value, whereas with the other method if variable fuz is set to
"x'; delete from foo where 'a' = 'a"
can you see what might happen?