Now you can convert your antiquated and dangerous Dynamic SQL to use Named Parameters automatically. Stop Injection Attacks and SQL failures from the use of aposthrophes in string variables.
One of my partners, Bill Ryan, wrote an excellent article on Dynamic SQL Needs to Die.I won't go into all of the problems he discussed that are associated with this dangerous methodology of creating SQL statements. As Bill pointed out, stored procedures are preferable to SQL, but sometimes it is not always possible to use a stored procedure.
However it is possible to never use Dynamic SQL. What we mean by Dynamic SQL is to create the SQL statement at run-time by concatenating strings and variables together.
Consider the following code. There are five potential bugs in it. Two of them are extremely likely to be hit. In the two lines colored Red, the code is concatenating text data from a text box. If the user happens to name the product or it's description with an aposthrophe (single quote) in it, which happens all the time, either on purpose or by accident, the SQL is bad and will cause a syntax error at run-time. The careless programmer's first question is, "why did you put a single quote in the product name?" The user's valid answer is, "because I could, what's wrong with it?" If the programmer has no concept of user interfaces and the way users think, which, sad to say, describes more developers than we wish to acknowledge, he or she will say, "you can't do that, Structured Query Language (as if the user has any idea what Structured Query Language is) doesn't allow aposthrophes in names!" No need to carry this discussion on, you get the picture.
| SQL = "update products " SQL &= "set productname = '" & .txtProductName.Text & "', " SQL &= "productdescription = '" & .txtProductDescription.Text & "', " SQL &= "priceperunit = " & UnFormat(.txtPricePerUnit.Text) & ", " SQL &= "Unitsinstock = " & .txtUnitsInStock.Text & ", " SQL &= "reorderlevel = " & .TextBox1.Text & " " SQL = SQL & "where productid = '" & .txtProductID.Text & "'" |
| SQL = "update products " SQL &= "set productname = '" & Replace(.txtProductName.Text, "'", "''") & "', " SQL &= "productdescription = '" & .txtProductDescription.Text & "', " SQL &= "priceperunit = " & UnFormat(.txtPricePerUnit.Text) & ", " SQL &= "Unitsinstock = " & .txtUnitsInStock.Text & ", " SQL &= "reorderlevel = " & .TextBox1.Text & " " SQL = SQL & "where productid = '" & .txtProductID.Text & "'" |
| Dim sqlCmd As New SqlClient.SqlCommand SQL = "update products " SQL &= "set productname = @dbParam1, " sqlCmd.Parameters.Add("@dbParam1", Replace(.txtProductName.Text, "'", "''")) SQL &= "productdescription = @dbParam2, " sqlCmd.Parameters.Add("@dbParam2", .txtProductDescription.Text) SQL &= "priceperunit = @dbParam3, " sqlCmd.Parameters.Add("@dbParam3", UnFormat(.txtPricePerUnit.Text)) SQL &= "Unitsinstock = @dbParam4, " sqlCmd.Parameters.Add("@dbParam4", .txtUnitsInStock.Text) SQL &= "reorderlevel = @dbParam5 " sqlCmd.Parameters.Add("@dbParam5", .TextBox1.Text) SQL = SQL & "where productid = @dbParam6" sqlCmd.Parameters.Add("@dbParam6", .txtProductID.Text) sqlCmd.CommandText = SQL sqlCmd.CommandType = CommandType.Text |
| sql ="select * "; sql += "from table ";// comment sql += "where a = '" + lname + "' "; /* comment */ sql += "and b = '" + fname + "' "; sql += "and c = " + citycode + " and d = 'a' " + " and e = " + citycode + " and f = '" + fname; sql += "' and datev = '" + DateAdd(1,1,Today) & "' "; |
| string sqlCmd = new SqlClient.SqlCommand(); sql ="select * "; sql += "from table "; sql += "where a = @dbParam1 "; sqlCmd.Parameters.Add("@dbParam1", lname); sql += "and b = @dbParam2 "; sqlCmd.Parameters.Add("@dbParam2", fname); sql += "and c = @dbParam3 " + " and d = 'a' " + " and e = @dbParam4 and f = '" + "@dbParam5"; sqlCmd.Parameters.Add("@dbParam3", citycode); sqlCmd.Parameters.Add("@dbParam4", citycode); sqlCmd.Parameters.Add("@dbParam5", fname); sql += "' and datev = @dbParam6 "; sqlCmd.Parameters.Add("@dbParam6", DateAdd(1,1,Today)); sqlCmd.CommandText = sql; sqlCmd.CommandType = CommandType.Text; |