how to change sql statement to parameterized query? - c#

I have an sql query that I need change to parameters so I can avoid sql injection.
adapter.SelectCommand.CommandText = #"SELECT c.*,(Select Initials FROM users WHERE User_ID = c.CreatedByUser) AS CreatedBy, (SELECT Initials FROM users WHERE User_ID = c.ModifiedByUser) AS ModifiedBy FROM currency c WHERE c.Company_ID = " + Company_ID + " AND c.CurrencyCode = '" + Code.Replace("'", "''") + "' ORDER BY c.Description
adapter.SelectCommand.Parameters.Add(new MySqlParameter("company_ID", Company_ID));
adapter.SelectCommand.Parameters.Add(new MySqlParameter("code", Code));
I know for Company_ID I need to change it to WHERE c.Company_ID = ?company_ID but I am not sure what to do for c.CurrencyCode = '" + Code.Replace("'", "''") + "'
I just don't know how to change the Code.Replace part, since its not a simple as company_ID

As per here
Try using (for odbc for example):
cmd.Parameters.Add("?CURRENCY", OdbcType.VarChar, Code.Replace("'", "''"))
Odbc approach
OdbcCommand cmd = sql.CreateCommand();
cmd.CommandText = "SELECT UNIQUE_ID FROM userdetails WHERE USER_ID IN (?, ?)";
cmd.Parameters.Add("?ID1", OdbcType.VarChar, 250).Value = email1;
cmd.Parameters.Add("?ID2", OdbcType.VarChar, 250).Value = email2;
For oracle:
//create SQL and insert parameters
OracleCommand cmd = new OracleCommand("insert into daily_cdr_logs (message) values (:_message)", con);
cmd.Parameters.Add(new OracleParameter("_message", msg));
For mysql:
cmd = new MySqlCommand("SELECT * FROM admin WHERE admin_username=#val1 AND admin_password=PASSWORD(#val2)", MySqlConn.conn);
cmd.Parameters.AddWithValue("#val1", tboxUserName.Text);
cmd.Parameters.AddWithValue("#val2", tboxPassword.Text);
cmd.Prepare();

So a parameterized query (to me at least) generally means that you have created a stored procedure on your database and then use your code to execute the stored procedure while passing in the relevant parameters.
This has a couple of benefits
DRY - you don't have to repeat the query in code, you can just call the execute method and pass in the appropriate parameters
Helps prevent SQL injection - You can only modify the parameters which hopefully will be sanitized before being passed to the query
Here is how to create a stored procedure according to MSDN
and
Here is how to execute a a stored procedure according to MSDN
If you are determined to do it via LINQ, MSDN has what you are looking for here
EDIT: It seems you are concerned about sql-injection (which is good!), here is an article (again from MSDN) that covers that topic pretty extensively

I have the answer. c.CurrencyCode = '" + Code.Replace("'", "''") + "' simply changes to c.CurrencyCode = ?code

Related

My query keeps rubbish in my sql table if it will not be complete properly

I'm using a a multiple query with insert and update statement together.
The problem is that if query will not be completed(for some reason e.x bad internet connection) my SQL Server table keeps rubbish.
Example of query:
SqlCommand cmd = new SqlCommand("INSERT INTO CustomerTrans (TableName, UserID, UserName, SumQuantity, SumPrice, SumRealPrice, SumExtrasPrice, SumTotal, SumDiscountTotal, DateTime) SELECT " + Connection.TableName + ",' " + Connection.UserID + "', '" + Connection.Username + "',Sum(Quantity),Sum(Price),Sum(RealPrice),Sum(ExtrasPrice), Sum(Quantity * Price),Sum(Quantity * DiscountPrice),'" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "' from InventoryTransTemp where active=1 and TableName=" + Connection.TableName + ";update InventorytransTemp set TrnDocumentID=(select max(TrnDocumentID) from CustomerTrans where UserID='" + Connection.UserID + "'),Active=0 where TableName=" + Connection.TableName + " and Active=1", con);
cmd.ExecuteNonQuery();
Take a photo from a query which has not be completed properly look query 2989 it has NULL values. I want to avoid inserting something if query is not be completed properly.
Sorry for my previous Question it was Unclear
Try it like this:
string sql =
"INSERT INTO CustomerTrans" +
" (TableName, UserID, UserName, SumQuantity, SumPrice, SumRealPrice, SumExtrasPrice, SumTotal, SumDiscountTotal, DateTime)" +
" SELECT #TableName, #UserID, #Username, Sum(Quantity), Sum(Price), Sum(RealPrice), Sum(ExtrasPrice), Sum(Quantity * Price), Sum(Quantity * DiscountPrice), current_timestamp" +
" FROM InventoryTransTemp" +
" WHERE active=1 and TableName= #TableName;\n" +
"SELECT #TranID = scope_identity;\n"
"UPDATE InventorytransTemp" +
" SET TrnDocumentID=#TranID ,Active=0" +
" WHERE TableName= #Tablename and Active=1;";
using (var con = new SqlConnection("connection string here"))
using (var cmd = new SqlCommand(sql, con))
{
//I'm guessing at exact column types/lengths here.
// You should update this to use your exact column types and lengths.
// Don't let ADO.Net try to guess this for you.
cmd.Parameters.Add("#TableName", SqlDbType.NVarChar, 20).Value = Connection.TableName;
cmd.Parameters.Add("#UserID", SqlDbType.Int).Value = Connection.UserID;
cmd.Parameters.Add("#Username", SqlDbType.NVarChar, 20).Value = Connection.Username;
cmd.Parameters.Add("#TranID", SqlDbType.Int).Value = 0; //placeholder only
con.Open();
cmd.ExecuteNonQuery();
}
Note the improved formatting of the query, the use of scope_identity() to get the new identity value rather than a nested select statement that might not be atomic, that I avoided ALL uses of string concatenation to substitute data into the query, that I avoided the AddWithValue() method entirely in favor of an option that doesn't try to guess at your parameter types, and the use of using blocks to be sure the SqlClient objects are disposed properly.
The only thing I'm still concerned about is if your INSERT/SELECT operation might create more than one new record. In that case, you'll need to handle this a different way that probably involves explicit BEGIN TRANSACTION/COMMIT statements, because this code only gets one #TranID value. But in that case, the original code was broken, too.

execute sql command in asp.net

I have a problem with executing a sql command to the DB. The command should add a new user to the 'users' table.
But when I run the code, I get this Exception on:
command.ExecuteNonQuery();
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Data.OleDb.OleDbException: Syntax error in INSERT INTO statement.
this is the code of the page - GetSignIn.cshtml :
#{
string Uname = Request["name"];
string userName = Request["userName"];
string pass = Request["passWord"];
string pic = Request["pic"];
string privacy = Request["privacy"];
if(pic == null)
{
pic = "Shared/defaultPic.jpg";
}
System.Data.OleDb.OleDbConnection connection = new System.Data.OleDb.OleDbConnection();
connection.ConnectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\Etay\Documents\Visual Studio 2012\WebSites\Josef\Shared\users.mdb";
try
{
System.Data.OleDb.OleDbCommand command = new System.Data.OleDb.OleDbCommand();
command.Connection = connection;
connection.Open();
command.CommandText = "INSERT INTO users (userName,passWord,Uname,pic) VALUES ('" + userName + "', '" + pass + "', '" + Uname + "', '" + pass + "', " + pic + ")";
command.ExecuteNonQuery();
Response.Redirect("../HtmlPage.html");
}
finally
{
connection.Close();
}
}
What should I change in my code? Why is it happening? Where is the syntax error in the INSERT INTO?
Use parameterized queries. Here is your statement rewritten to make use of them.
I replaced your try/finally with a using block although your try/finally was acceptable.
Parameterized queries prevent errors and Sql Injection Attacks. An error could occur in your existing code if I were to submit a tick as a part of my user name or password. In the current form this would result in an exception. This is because the tick character is used to quote strings in sql syntax.
using (System.Data.OleDb.OleDbConnection connection = new System.Data.OleDb.OleDbConnection())
{
connection.ConnectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\Etay\Documents\Visual Studio 2012\WebSites\Josef\Shared\users.mdb";
using (System.Data.OleDb.OleDbCommand command = new System.Data.OleDb.OleDbCommand())
{
command.Connection = connection;
command.CommandText = "INSERT INTO users (userName,passWord,Uname,pic) VALUES (?,?,?,?)";
command.Parameters.Add(userName);
command.Parameters.Add(pass);
command.Parameters.Add(Uname);
command.Parameters.Add(pic);
connection.Open();
command.ExecuteNonQuery();
}
}
About parameters for an OleDb connection from OleDbCommand.Parameters
Remarks
The OLE DB .NET Provider does not support named parameters for passing parameters to an SQL statement or a stored procedure called by an OleDbCommand when CommandType is set to Text. In this case, the question mark (?) placeholder must be used. For example:
SELECT * FROM Customers WHERE CustomerID = ?
Therefore, the order in which OleDbParameter objects are added to the OleDbParameterCollection must directly correspond to the position of the question mark placeholder for the parameter in the command text.
What should I change in my code?
Change to parameters (that also fixes the problem that you don;t have quotes around the pic value)
Remove the second instance of pass in your values
command.CommandText = "INSERT INTO users (userName,passWord,Uname,pic) VALUES (#userName, #pass, #Uname, #pic)";
command.Parameters.Add("#userName").Value = userName;
.. etc.
It's unclear what the type if pic is - you are passing a string but I can;t tell of the column stores a file path or if you are indending to serialize the file and store it in a pinary field.
You set 4 fields after the "INTO" clause, however you're passing 5 parameters:
"INSERT INTO users (userName,passWord,Uname,pic) VALUES ('" + userName + "', '" + pass + "', '" + Uname + "', '" + pass + "', " + pic + ")";
Just add the fifth field, or remove one parameter from the VALUES part
Please check take a look at your Insert statement, it looks like that you provided password value twice.
The number of query values and the destination fields should be same in an INSERT statement.
You have the wrong number parameters in your insert statement. For clarity, why not use string.Format to keep everything uniform? (Assuming these are all string types)
var rawSql = #"Insert INTO Users (userName,passWord,Uname,pic) VALUES ('{0}','{1}','{2}','{3}')";
command.CommandText = string.Format(rawSql, userName, pass, Uname, pic);
command.ExecuteNonQuery();
However, it also looks like you probably want to include that 5th parameter as well - just extend the format :
var rawSql = #"Insert INTO Users (userName,passWord,Uname,pic, privacy) VALUES ('{0}','{1}','{2}','{3}','{4}')";
command.CommandText = string.Format(rawSql, userName, pass, Uname, pic, privacy);
command.ExecuteNonQuery();
Since most of the answers failed to address the SQL Injection vulnerability, here's an example with parameterized queries. In addition to preventing SQL Injection attacks, it also makes it easier to troubleshoot these types of issues, and you don't need to worry about quoting or not quoting parameters.
System.Data.OleDb.OleDbConnection connection = new System.Data.OleDb.OleDbConnection();
connection.ConnectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\Etay\Documents\Visual Studio 2012\WebSites\Josef\Shared\users.mdb";
try
{
System.Data.OleDb.OleDbCommand command = new System.Data.OleDb.OleDbCommand();
command.Connection = connection;
connection.Open();
command.CommandText = "INSERT INTO users (userName, passWord, Uname, pic, privacy) VALUES (?, ?, ?, ?, ?)";
command.Parameters.Add(userName);
command.Parameters.Add(pass);
command.Parameters.Add(name);
command.Parameters.Add(pic);
command.Parameters.Add(privacy);
command.ExecuteNonQuery();
Response.Redirect("../HtmlPage.html");
}
finally
{
connection.Close();
}
Tnx 4 the help
It happend to be a problem with the database - you can not apply a INSERT INTO statement where the column name is "password". "password" is a Reserved word
in SQL.
Tnx again,
Etay

Syntax error in UPDATE statement OleDb Exception

I check my SQL Statement many times and it seems that my SQL Statement is Error. I don't why it doesn't work. My SQL Statement is correct and It resulted to this OleDBException "Syntax error in UPDATE statement.".
Here is the code
OleDbConnection CN = new OleDbConnection(mysql.CON.ConnectionString);
CN.Open();
cmd1 = new OleDbCommand("Update Mosque Set Name='" + txtNAME.Text + "', No='" + Convert.ToInt32(txtNO.Text) + "', place='" + txtPlace.Text + "', group='" + txtGroup.Text + "', description='" + txtdec.Text + "' where id='" + txtID.Text + "'", CN);
cmd1.ExecuteNonQuery();
CN.Close();
need help please to know what is the error here
I don't know what database are you using, but I am sure that GROUP is a reserved keyword in practically any existant SQL database. This word cannot be used without some kind of delimiter around it. The exact kind of delimiter depend on the database kind. What database are you using?
Said that, please do not use string concatenation to build sql commands, but use always a parameterized query. This will allow you to remove any possibilities of Sql Injection and avoid any syntax error if one or more of your input string contains a single quote somewhere
So, supposing you are using a MS Access Database (In Access also the word NO is a reserved keyword and the delimiters for reserved keywords are the square brakets) you could write something like this
string commandText = "Update Mosque Set Name=?, [No]=?, place=?, " +
"[Group]=?, description=? where id=?"
using(OleDbConnection CN = new OleDbConnection(mysql.CON.ConnectionString))
using(OleDbCommand cmd1 = new OleDbCommand(commandText, CN))
{
CN.Open();
cmd1.Parameters.AddWithValue("#p1",txtNAME.Text);
cmd1.Parameters.AddWithValue("#p2",Convert.ToInt32(txtNO.Text));
cmd1.Parameters.AddWithValue("#p3",txtPlace.Text);
cmd1.Parameters.AddWithValue("#p4",txtGroup.Text);
cmd1.Parameters.AddWithValue("#p5",txtdec.Text);
cmd1.Parameters.AddWithValue("#p6",txtID.Text);
cmd1.ExecuteNonQuery();
}
Instead for MySQL you have to use the backticks around the GROUP keyword
string commandText = "Update Mosque Set Name=?, No=?, place=?, " +
"`Group`=?, description=? where id=?"
Hard to tell without knowing the values of the texboxes, but I suspect that one of them has an apostrophe which is causing an invalid syntax.
I recommend using parameters instead:
cmd1 = new OleDbCommand("Update Mosque Set [Name]=#Name, [No]=#No, [place]=#Place, [group]=#Group, [description]=#Description WHERE id=#ID", CN);
cmd1.Parameters.AddWithValue("#Name",txtNAME.Text);
cmd1.Parameters.AddWithValue("#No",Convert.ToInt32(txtNO.Text));
// etc.

In C# how to get value from text box using quotes

In my program i need to get value from the database , so using a texbox so that client type anything and i can search from database.
My code is
SqlCommand sqlcmd = sqlcon.CreateCommand();
sqlcmd.CommandText = "Select distinct transactionName from dbo.tbl where terminalId = " + textBox_cardNumber.Text;
the above is not my full code but here in my code i am using textbox_cardNumber ...
I want that in quotes ''
it should be like
Select distinct transactionName from dbo.tbl where terminalId = '0097'
So my question is how to get in quotes???
Use a parameterized query like this
SqlCommand sqlcmd = sqlcon.CreateCommand();
sqlcmd.CommandText = "Select distinct transactionName from dbo.tbl " +
"where terminalId = #id";
sqlCmd.Parameters.AddWithValue("#id", textBox_cardNumber.Text);
....
In this way you defer the job to recognize your data (the textbox text) as a string to the Framework code that knows how to correctly quote your value. Also you remove the possibilities of Sql Injection attacks
"'" + textBox_cardNumber.Text + "'";
I hope I understood you!
You can also try this, but this is not good practice, used always Parameter.
sqlcmd.CommandText = "Select distinct transactionName from dbo.tbl where terminalId = '" + textBox_cardNumber.Text +"'";
You can try this code:
SqlCommand sqlcmd = sqlcon.CreateCommand();
sqlcmd.CommandText = "Select distinct transactionName from dbo.tbl where terminalId = '"
+ textBox_cardNumber.Text+"'";
Instead of string concatenation, you can should use parameterized sql instead. Because this kind of codes are open for SQL Injection attacks.
SqlCommand sqlcmd = sqlcon.CreateCommand();
sqlcmd.CommandText = "SELECT DISTINCT transactionName FROM dbo.tbl
WHERE terminalId = #terminalID";
sqlcmd.Parameters.AddWithValue("#terminalID", textBox_cardNumber.Text);
A side note, take a look at SQL Injection Attacks by Example
You need to make use of prepared statements in which you use parameters.
Otherwise, you need to add quotes around your input string, but it will leave you open for SQL injection

Help me Fix this SQL Statement?

Can someone let me know what is wrong with my SQL Statement and how I can improve it?
da = new SqlDataAdapter("SELECT * FROM Guests"+" WHERE Students.name='" +
byNametextBox.Text + "'", MyConn);
An EXISTS predicate is slightly more efficient than a JOIN if you want only columns from one of the tables. Additionaly - never inject strings into SQL statements like that - you're just begging for SQL Injection attacks, or related crashes errors (Yes, I know it's a Forms application, but the same holds true. If you're searching for a name like "O'Leary", you'll get a crash).
SqlCommand cmd = new SqlCommand("SELECT * FROM Guests WHERE EXISTS (SELECT Id FROM Students WHERE Guests.StudentId = Students.Id And Students.name= #name)", MyConn);
cmd.Parameters.Add("#name", SqlDbType.VarChar, 50).Value = byNametextBox.Text;
SqlDataAdapter adapt = new SqlDataAdapter(cmd);
Note: Some people may argue that "SELECT *" is bad, and that you should consider specifying individual column names
You need to worry about SQL Injection. Put simply, SQL Injection is when a user is able to put arbitrary SQL statements into your query. To get around this, either use a Stored Procedure or a Parametrized SQL Query. An Example of a Parametrized SQL query is below:
SqlConnection conn = null;
SqlDataReader reader = null;
//Connection string goes here
string studentName = byNametextBox.Text;
SqlCommand cmd = new SqlCommand(
"SELECT * FROM Guests "+" WHERE Students.name = #name", conn);
SqlParameter param = new SqlParameter("#name", SqlDbType.NVarChar, 50);
param.Value = studentName;
cmd.Parameters.Add(param);
reader = cmd.ExecuteReader();
//Do stuff with reader here
SqlDataAdapter("SELECT Guests.* FROM Guests,Students WHERE Guest.StudentId = Student.Id and Students.name='" + byNametextBox.Text + "'", MyConn);`
You need an Inner Join. I think it would be something like this:
SELECT Guests.* FROM Guests INNER JOIN Students ON Students.name = Guests.name WHERE Students.name = '" + byNametextBox.Text + "'"
Try it:
"SELECT g.*
FROM Guests g
INNER JOIN Students s ON g.StudentId = s.StudentId
WHERE Students.Name = '" + byNametextBox.Text + '"'
Assuming that the field wich relates both tables is StudentId.
Beware that SQL is not the same between different Servers. This statement will work on Sql Server, I don't know in others. Also, beware that you aren't protecting yourself on SQL Injection attacks. You should perform your query with parameters, instead of concatenating strings in the way you are doing it.
This is a simple query that you should know by yourself. You can search for tutorials on Google, but here is a generic introduction.

Categories

Resources