I tried to update a paragraph from mysql table,but i got error like this
"You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near 's first-ever super-villainess."
My mysql Query
cmd.CommandText = "UPDATE `moviemaster` SET `Runtime`='" + runtime + "',`DateMasterId`='" + dateid + "',`Trailer`='" + trailer + "',`Synopsis`='" + synopsis + "' WHERE `MovieMasterId`='" + movieid + "'";
I got error in 'synopsis',it's a big data containing a large paragraph.If i romove 'Synopsis' section from the query,everything working fine.What exactly the problem.How can i resolve this?
#SonerGönül:Ok,fine.. then please show me an example of parameterised
query
Sure. I also wanna add a few best practice as well.
Use using statement to dispose your connection and command automatically.
You don't need to escape every column with `` characters. You should only escape if they are reserved keywords for your db provider. Of course, at the end, changing them to non-reserved words is better.
Do not use AddWithValue method. It may generate upexpected and surprising result sometimes. Use Add method overload to specify your parameter type and it's size.
using (var con = new SqlConnection(conString))
using(var cmd = con.CreateCommand())
{
cmd.CommandText = #"UPDATE moviemaster
SET Runtime = #runtime, DateMasterId = #dateid, Trailer = #trailer, Synopsis = #synopsis
WHERE MovieMasterId = #movieid";
cmd.Parameters.Add("#runtime", MySqlDbType.VarChar).Value = runtime; ;
cmd.Parameters.Add("#dateid", MySqlDbType.VarChar).Value = dateid;
cmd.Parameters.Add("#trailer", MySqlDbType.VarChar).Value = trailer;
cmd.Parameters.Add("#synopsis", MySqlDbType.VarChar).Value = synopsis;
cmd.Parameters.Add("#movieid", MySqlDbType.VarChar).Value = movieid;
// I assumed your column types are VarChar.
con.Open();
cmd.ExecuteNonQuery();
}
Please avoid using inline query. Your database can be subjected to SQL Injection. See this example, on what can be done using SQL Injection.
And use paramterized query instead. Here is the example taken from here. This way, even if your string has special characters, it will not break and let you insert/update/select based on parameters.
private String readCommand = "SELECT LEVEL FROM USERS WHERE VAL_1 = #param_val_1 AND VAL_2 = #param_val_2;";
public bool read(string id)
{
level = -1;
MySqlCommand m = new MySqlCommand(readCommand);
m.Parameters.AddWithValue("#param_val_1", val1);
m.Parameters.AddWithValue("#param_val_2", val2);
level = Convert.ToInt32(m.ExecuteScalar());
return true;
}
and finally, your query will become
cmd.CommandText = "UPDATE `moviemaster` SET `Runtime`= #param1,`DateMasterId`= #dateid, `Trailer`= #trailer,`Synopsis`= #synopsis WHERE `MovieMasterId`= #movieid";
cmd.Parameters.AddWithValue("#param1", runtime);
cmd.Parameters.AddWithValue("#dateid", dateid);
cmd.Parameters.AddWithValue("#trailer", trailer);
cmd.Parameters.AddWithValue("#synopsis", synopsis);
cmd.Parameters.AddWithValue("#movieid", movieid);
Related
I have a slight issue, I have a ASP.NET Webforms application. I'm sending over a url?id=X were X is my database index or id.
I have a C# class file to run my SQL connection and query. Here is the code:
public DataTable ViewProduct(string id)
{
try
{
string cmdStr = "SELECT * Products WHERE Idx_ProductId = " + id;
DBOps dbops = new DBOps();
DataTable vpTbl = dbops.RetrieveTable(cmdStr, ConfigurationManager.ConnectionStrings["MyDatabase"].ConnectionString);
return vpTbl;
}
catch (Exception e)
{
return null;
}
}
So as you can see my problem lies within string cmdStr = "SQL Query" + variable;
I'm passing over my index or id through the URL then requesting it and turning it into a string then using ViewProduct(productId).
I don't know what syntax or how to add the id into my C# string sql query. I've tried:
string cmdStr = "SELECT * Products WHERE Idx_ProductId = #0" + id;
string cmdStr = "SELECT * Products WHERE Idx_ProductId = {0}" + id;
also what I have currently to no avail.
I was so sure this would be a duplicate of some canonical question about parameterized queries in C#, but apparently there isn't one (see this)!
You should parameterize your query - if you don't, you run the risk of a malicious piece of code injecting itself into your query. For example, if your current code could run against the database, it would be trivial to make that code do something like this:
// string id = "1 OR 1=1"
"SELECT * Products WHERE Idx_ProductId = 1 OR 1=1" // will return all product rows
// string id = "NULL; SELECT * FROM UserPasswords" - return contents of another table
// string id = "NULL; DROP TABLE Products" - uh oh
// etc....
ADO.NET provides very simple functionality to parameterize your queries, and your DBOps class most assuredly is not using it (you're passing in a built up command string). Instead you should do something like this:
public DataTable ViewProduct(string id)
{
try
{
string connStr = ConfigurationManager.ConnectionStrings["MyDatabase"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open();
using (SqlCommand cmd = conn.CreateCommand())
{
// #id is very important here!
// this should really be refactored - SELECT * is a bad idea
// someone might add or remove a column you expect, or change the order of columns at some point
cmd.CommandText = "SELECT * Products WHERE Idx_ProductId = #id";
// this will properly escape/prevent malicious versions of id
// use the correct type - if it's int, SqlDbType.Int, etc.
cmd.Parameters.Add("#id", SqlDbType.Varchar).Value = id;
using (SqlDataReader reader = cmd.ExecuteReader())
{
DataTable vpTbl = new DataTable();
vpTbl.Load(reader);
return vpTbl;
}
}
}
}
catch (Exception e)
{
// do some meaningful logging, possibly "throw;" exception - don't just return null!
// callers won't know why null got returned - because there are no rows? because the connection couldn't be made to the database? because of something else?
}
}
Now, if someone tries to pass "NULL; SELECT * FROM SensitiveData", it will be properly parameterized. ADO.NET/Sql Server will convert this to:
DECLARE #id VARCHAR(100) = 'NULL; SELECT * FROM SensitiveData';
SELECT * FROM PRoducts WHERE Idx_ProductId = #id;
which will return no results (unless you have a Idx_ProductId that actually is that string) instead of returning the results of the second SELECT.
Some additional reading:
https://security.stackexchange.com/questions/25684/how-can-i-explain-sql-injection-without-technical-jargon
Difference between Parameters.Add and Parameters.AddWithValue
SQL injection on INSERT
Avoiding SQL injection without parameters
How do I create a parameterized SQL query? Why Should I? (VB.NET)
How can I prevent SQL injection in PHP? (PHP specific, but many helpful points)
Is there a canonical question telling people why they should use SQL parameters?
What type Products.Idx_ProductId is?
Probably it is string, than you need to use quotes: "... = '" + id.Trim() + "'";
SqlConnection cn = new SqlConnection("user id=ID;" +
"password=PASS;server=svr;" +
"Trusted_Connection=no;" +
"database=db; " +
"connection timeout=30");
cn.Open();
SqlCommand command1 = new SqlCommand();
command1.Connection = cn;
Console.WriteLine(ListofOrders.Count);
for (int i = 0; i < ListofOrders.Count; i++)
command1.CommandText += string.Format("update table set Status='Expired' where GUID={0};", ListofOrders[i].ToString());
command1.ExecuteNonQuery();
// LogicHandler.UpdateActiveOrders();
Console.WriteLine("DONE", ConsoleColor.Cyan);
Getting error at this step: command1.ExecuteNonQuery(); Error Message: The multi-part identifier could not be bound.
What i am trying here is I am running a select query and getting that data into the ListofOrders list from that I wanna run the update to those data in the list.
Please help
If you use a Reserved Keyword like table you have to wrap it in square brackets: [table]. But it would be better to not use them in the first place.
I guess you need to wrap the Guid with apostrophes like in GUID='{0}'. Howver, you should use sql-parameters instead of string concatenation, always. That prevents also sql-injection.
string update = #"update tablename -- or [Table] but i wouldnt do that
set Status='Expired'
where GUID=#GUID";
command1.CommandText = update;
command1.Parameters.Add("#GUID", SqlDbType.UniqueIdentifier).Value = new Guid(ListofOrders[i].ToString());
As an aside, why have you used command1.CommandText += instead of just command1.CommandText =? That is at least confusing, if you reuse the command it could also cause errors.
I'm running a query from a web form to update records. Since I'm just learning about C#, I'm using a command string as opposed to a stored procedure.
My update method is as follows:
public void updateOne()
{
string commandText = "update INVOICE SET <Redacted> = #<Redacted>,
Supplier = #Sup, SupplierName = #SupN, NetTotal = #Net,
VATTotal = #VAT, InvoiceDate = #InvDt "
<needed a line break here, which is why I split the string again>
+ "WHERE K_INVOICE = #K_INV";
using (SqlConnection dbConnection = new SqlConnection
(conParams.connectionString))
{
SqlCommand cmd = new SqlCommand(commandText, dbConnection);
cmd.Parameters.Add("#K_INV", SqlDbType.Int);
cmd.Parameters["#K_INV"].Value = #K_INV;
cmd.Parameters.AddWithValue("#<Redacted>", #<Redacted>.ToString());
cmd.Parameters.AddWithValue("#Sup", #Sup.ToString());
cmd.Parameters.AddWithValue("#SupN", #SupN.ToString());
cmd.Parameters.AddWithValue("#Net", #Net.ToString());
cmd.Parameters.AddWithValue("VAT", #VAT.ToString());
cmd.Parameters.AddWithValue("#InvDt", #InvDt.ToString());
try
{
dbConnection.Open();
cmd.ExecuteNonQuery();
}
catch (Exception e)
{
errorString = e.Message.ToString();
}
}
}
Catch stalls on an SQL error (Incorrect syntax near SET), and I have an idea that the issue occurs because I convert the parameters to strings. The first parameter is an Int, which should be OK.
If this is the case, what should I convert the parameters to? If not, what on earth is wrong?
Try to add a # before the string to escape the breaklines, for sample:
string commandText = #"update INVOICE SET [Redacted] = #Redacted,
Supplier = #Sup, SupplierName = #SupN, NetTotal = #Net,
VATTotal = #VAT, InvoiceDate = #InvDt "
+ "WHERE K_INVOICE = #K_INV";
In parameterName argument you can add the # but the value not, just the variable, for sample
cmd.Parameters.AddWithValue("#Redacted", redacted.ToString());
Try to execute this query in the databse with some values to check if everything is correct. You could use [brackets] in the table name and column names if you have a reserved word.
I would recommend you read this blog article on the dangers of .AddWithValue():
Can we stop using AddWithValue already?
Instead of
cmd.Parameters.AddWithValue("#Sup", #Sup.ToString());
you should use
cmd.Parameters.Add("#Sup", SqlDbType.VarChar, 50).Value = ...(provide value here)..;
(is your variable in C# really called #SupN ?? Rather unusual and confusing....)
I would recommend to always define an explicit length for any string parameters you define
Hi there its the first time to use stackoverflow so hi every one L)
i'm a beginner into C# forms i take it as a fun hobby.
SqlCommand comm = new SqlCommand("SELECT COUNT(*) FROM Members where sponser = "
+textbox1.text+"'", connection);
Int32 count = (Int32)comm.ExecuteScalar();
textbox2.Text ="Found "+ count+" Members;
well its just a mix between 2 codes i have got from google xD
how ever the error appear here textbox2.Text ="Found "+ count+" Members;
There are a couple of things wrong with this line of code:
textbox2.Text ="Found "+ count+" Members;
First of all, there's a syntax error. You never close the second set of quotes. You'd do so like this:
textbox2.Text ="Found "+ count+" Members";
However, string concatenation like this is still a little messy. You have two literal strings and you're trying to add them to an integer, which isn't entirely intuitive (and probably slower than it needs to be). Instead, consider using a formatting string:
textbox2.Text = string.Format("Found {0} Members", count);
This will take the value from count (which is an integer) and, internally to the string.Format() function, discern its string representation and insert it into the placeholder in the formatted string.
UPDATE: That takes care of the compile-time errors. Now you're going to get a run-time error from this:
SqlCommand comm = new SqlCommand("SELECT COUNT(*) FROM Members where sponser = "
+textbox1.text+"'", connection);
As soon as you try to execute that SQL statement you're going to get an error from the database because the resulting query has a syntax error:
SELECT COUNT(*) FROM Members where sponser = some text'
You're missing the opening single-quote for the parameter. Something like this:
SqlCommand comm = new SqlCommand("SELECT COUNT(*) FROM Members where sponser = '"
+textbox1.text+"'", connection);
However, and this is important, you're still not done. This line of code is wide open to a very common and easily exploitable vulnerability called SQL Injection. You'll want to move away from direct string concatenation and use parameters for your SQL queries. Something like this:
SqlCommand cmd = new SqlCommand("SELECT COUNT(*) FROM Members where sponser = #sponser");
cmd.Parameters.Add("#sponser", textbox1.text);
Int32 count = (Int32)comm.ExecuteScalar();
Know that there is still a lot more you can do to improve this, which is all worth learning over time. Things you can look into are:
Checking and validating user input (textbox1.text) before you even try to use it in a SQL query.
Checking the output of comm.ExecuteScalar() before trying to directly cast it to an Int32 (this would give you a runtime error if it returns anything other than an integer for some reason).
Consider using something like Linq to Sql in place of ADO.NET components as it does a lot more for you with less code on your part.
protected void Page_Load(object sender, EventArgs e)
{
lb1.Text = GetRecordCount(textbox2.Text).ToString();
}
private int GetRecordCount(string myParameter)
{
string connectionString = ConfigurationManager.ConnectionStrings["DBConnection"].ToString();
Int32 count = 0;
string sql = "SELECT COUNT(*) FROM members WHERE sponsor = #Sponsor";
using (SqlConnection conn = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.Parameters.Add("#Sponsor", SqlDbType.VarChar);
cmd.Parameters["#Sponsor"].Value = myParameter;
try
{
conn.Open();
count = (Int32)cmd.ExecuteScalar();
}
catch (Exception ex)
{
}
}
return (int)count;
}
You are missing a closing " at the end:
textbox2.Text ="Found "+ count+" Members";
You code is vulnerable to SQL Injections. Please consider using Parameters.
private int GetMemberCount(string connectionString, string sponsor)
{
using(var connection = new SqlConnection(connectionString))
using(var command = connection.CreateCommand())
{
command.CommandText = "SELECT COUNT(*) FROM members WHERE sponsor = #Sponsor";
command.Parameters.AddWithValue("#Sponsor", sponsor);
return Convert.ToInt32(command.ExecuteScalar());
}
}
//Usage
var sponsor = textbox1.text;
var count = GetMemberCount(connectionString, sponsor);
textbox2.Text = string.Format("Found {0} Members", count);
Currently, I am creating an SQL Query by doing something like
string SQLQuery = "SELECT * FROM table WHERE ";
foreach(word in allTheseWords)
{
SQLQuery = SQLQuery + " column1 = '" + word + "' AND";
}
I understand that this can lead to an SQL Injection attack. I don't know how to pass an array as a parameter
where report in #allTheseWords
===========
I am using SQL Server 2012
Unfortunately, you cannot pass an array as a parameter without adding a user-defined type for table-valued parameters. The simplest way around this restriction is to create individually named parameters for each element of the array in a loop, and then bind the values to each of these elements:
string SQLQuery = "SELECT * FROM table WHERE column1 in (";
for(int i = 0 ; i != words.Count ; i++) {
if (i != 0) SQLQuery += ",";
SQLQuery += "#word"+i;
}
...
for(int i = 0 ; i != words.Count ; i++) {
command.Parameters.Add("#word"+i, DbType.String).Value = words[i];
}
You can also create a temporary table, insert individual words in it, and then do a query that inner-joins with the temp table of words.
Here is the recommendation from Microsoft:
Use Code Analysis to detect areas in your Visual Studio projects that are prone to sql injection;
Refer to the article on how to reduce risk of attack:
On short they talk about:
using a stored procedure.
using a parameterized command string.
validating the user input for both type and content before you build the command string.
Btw, you can enable static analysis as part of your build process and configure it so that when a security rule is broken, the build also breaks. Great way to make sure your team writes secure code!
Using ADO you can do it with the help of params
SqlConnection Con = new SqlConnection(conString);
SqlCommand Com = new SqlCommand();
string SQLQuery = "SELECT * FROM table WHERE ";
int i=1;
foreach(word in words)
{
Com.Parameters.Add("#word"+i.ToString(),SqlDbType.Text).Value = word;
SQLQuery = SQLQuery + " column1 = '#word"+i.ToString()+"' AND ";
i++;
}
Com.CommandText =SQLQuery;
For SQL Server, you'd use a Table-Valued Parameter. SQL has one structure that represents a collection of multiple items of the same type. It's called a table. It doesn't have arrays.
Of course, your supposed updated query:
where report in #allTheseWords
Isn't equivalent to your original query, but may be closer to the intent. In the query constructed using AND, you're saying that the same column, in the same row has to be equal to multiple different words. Unless all of the words are equal, this will never return any rows. The updated query answers whether any of the words match, rather than all.
You need to use prepared statements. The way those are handled is that you write your query and put placeholders for the values you want to use. Here's an example:
SELECT * FROM table WHERE column1 = #word
You then have to go through a prepare phase where the SQL engine knows it will need to bind parameters to the query. You can then execute the query. The SQL engine should know when and how to interpret the parameters you bind to your query.
Here's some code to do that:
SqlCommand command = new SqlCommand(null, rConn);
// Create and prepare an SQL statement.
command.CommandText = "SELECT * FROM table WHERE column1 = #word";
command.Parameters.Add ("#word", word);
command.Prepare();
command.ExecuteNonQuery();
I combine the use of params with HtmlEncoding(to get rid of special characters where not needed). Give that a shot.
using (SqlConnection conn = new SqlConnection(conString))
{
string sql = "SELECT * FROM table WHERE id = #id";
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.paramaters.AddWithValue("#id", System.Net.WebUtility.HtmlEncode(id));
conn.Open();
using (SqlDataReader rdr = cmd.ExecuteReader())
{
}
}
}