I've got a error which I can't understand. When I'm debugging and trying to run a insert statement, its throwing the following exception:
"There are fewer columns in the INSERT statement than values specified in the VALUES clause. The number of values in the VALUES clause must match the number of columns specified in the INSERT statement."
I have looked all over my code, and I can't find the mistake I've made.
This is the query and the surrounding code:
SqlConnection myCon = DBcon.getInstance().conn();
int id = gm.GetID("SELECT ListID from Indkøbsliste");
id++;
Console.WriteLine("LNr: " + listnr);
string streg = GetStregkode(navne);
Console.WriteLine("stregk :" + strege);
string navn = GetVareNavn(strege);
Console.WriteLine("navn :" + navne);
myCon.Open();
string query = "INSERT INTO Indkøbsliste (ListID, ListeNr, Stregkode, Navn, Antal, Pris) Values(" + id + "," + listnr + ", '" + strege + "','" + navn + "'," + il.Antal + ", "+il.Pris+")";
Console.WriteLine(il.Antal+" Antal");
Console.WriteLine(il.Pris+" Pris");
Console.WriteLine(id + " ID");
SqlCommand com = new SqlCommand(query, myCon);
com.ExecuteNonQuery();
com.Dispose();
myCon.Close();
First of all check the connection string and confirm the database location and number of columns a table has.
Suggestion : Do not use hardcoded SQL string. Use parameterized sql statements or stored-proc.
Try parameterized way,
string query = "INSERT INTO Indkøbsliste (ListID, ListeNr, Stregkode, Navn, Antal, Pris)
Values (#ListID, #ListeNr, #Stregkode, #Navn, #Antal, #Pris)"
SqlCommand com = new SqlCommand(query, myCon);
com.Parameters.Add("#ListID",System.Data.SqlDbType.Int).Value=id;
com.Parameters.Add("#ListeNr",System.Data.SqlDbType.Int).Value=listnr;
com.Parameters.Add("#Stregkode",System.Data.SqlDbType.VarChar).Value=strege ;
com.Parameters.Add("#Navn",System.Data.SqlDbType.VarChar).Value=navn ;
com.Parameters.Add("#Antal",System.Data.SqlDbType.Int).Value=il.Antal;
com.Parameters.Add("#Pris",System.Data.SqlDbType.Int).Value=il.Pris;
com.ExecuteNonQuery();
Please always use parametrized queries. This helps with errors like the one you have, and far more important protects against SQL injection (google the term, or check this blog entry - as an example).
For example, what are the actual values of strege and/or navn. Depending on that it may render your SQL statement syntactically invalid or do something worse.
It (looks like) a little more work in the beginning, but will pay off big time in the end.
Are you using danish culture settings?
In that case if il.Pris is a double or decimal it will be printed using comma, which means that your sql will have an extra comma.
Ie:
INSERT INTO Indkøbsliste (ListID, ListeNr, Stregkode, Navn, Antal, Pris) Values(33,5566, 'stegkode','somename',4, 99,44)
where 99,44 is the price.
The solution is to use parameters instead of using the values directly in you sql. See some of the other answers already explaining this.
Related
I have a query to insert a row into a table, which has a field called ID, which is populated using an AUTO_INCREMENT on the column. I need to get this value for the next bit of functionality, but when I run the following, it always returns 0 even though the actual value is not 0:
MySqlCommand comm = connect.CreateCommand();
comm.CommandText = insertInvoice;
comm.CommandText += "\'" + invoiceDate.ToString("yyyy:MM:dd hh:mm:ss") + "\', " + bookFee + ", " + adminFee + ", " + totalFee + ", " + customerID + ")";
int id = Convert.ToInt32(comm.ExecuteScalar());
According to my understanding, this should return the ID column, but it just returns 0 every time. Any ideas?
EDIT:
When I run:
"INSERT INTO INVOICE (INVOICE_DATE, BOOK_FEE, ADMIN_FEE, TOTAL_FEE, CUSTOMER_ID) VALUES ('2009:01:01 10:21:12', 50, 7, 57, 2134);last_insert_id();"
I get:
{"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 'last_insert_id()' at line 1"}
MySqlCommand comm = connect.CreateCommand();
comm.CommandText = insertStatement; // Set the insert statement
comm.ExecuteNonQuery(); // Execute the command
long id = comm.LastInsertedId; // Get the ID of the inserted item
[Edit: added "select" before references to last_insert_id()]
What about running "select last_insert_id();" after your insert?
MySqlCommand comm = connect.CreateCommand();
comm.CommandText = insertInvoice;
comm.CommandText += "\'" + invoiceDate.ToString("yyyy:MM:dd hh:mm:ss") + "\', "
+ bookFee + ", " + adminFee + ", " + totalFee + ", " + customerID + ");";
+ "select last_insert_id();"
int id = Convert.ToInt32(comm.ExecuteScalar());
Edit: As duffymo mentioned, you really would be well served using parameterized queries like this.
Edit: Until you switch over to a parameterized version, you might find peace with string.Format:
comm.CommandText = string.Format("{0} '{1}', {2}, {3}, {4}, {5}); select last_insert_id();",
insertInvoice, invoiceDate.ToString(...), bookFee, adminFee, totalFee, customerID);
Use LastInsertedId.
View my suggestion with example here: http://livshitz.wordpress.com/2011/10/28/returning-last-inserted-id-in-c-using-mysql-db-provider/
It bothers me to see anybody taking a Date and storing it in a database as a String. Why not have the column type reflect reality?
I'm also surprised to see a SQL query being built up using string concatenation. I'm a Java developer, and I don't know C# at all, but I'd wonder if there wasn't a binding mechanism along the lines of java.sql.PreparedStatement somewhere in the library? It's recommended for guarding against SQL injection attacks. Another benefit is possible performance benefits, because the SQL can be parsed, verified, cached once, and reused.
Actually, the ExecuteScalar method returns the first column of the first row of the DataSet being returned. In your case, you're only doing an Insert, you're not actually querying any data. You need to query the scope_identity() after you're insert (that's the syntax for SQL Server) and then you'll have your answer. See here:
Linkage
EDIT: As Michael Haren pointed out, you mentioned in your tag you're using MySql, use last_insert_id(); instead of scope_identity();
I Just Keep Having this Error:
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 '2014-10-08 19:39:57)' at line 1
public string ObtenerFechaHora()
{
string query = "select CURRENT_TIMESTAMP() as Fecha";
OpenConnection();
MySqlCommand cmd = new MySqlCommand(query, connection);
cmd.ExecuteNonQuery();
DateTime e = (DateTime)cmd.ExecuteScalar();
CloseConnection();
return e.ToString("yyyy-MM-dd H:mm:ss");
}
Then i insert ("Fecha" is the DateTime Column)
string query = "INSERT INTO actividad (idTerminal, Proceso, Nombre, Tiempo, Fecha) VALUES('" + idTerminal + "', '" + Proceso + "', '" + Nombre + "', '1,'" + this.ObtenerFechaHora() + ")";
I been used loot of formats and i keep having error, for example:
e.ToString("yyyy-MM-dd H:mm:ss");
e.ToString("yyyy-MM-dd HH:mm:ss");
e.ToString("dd-MM-yyyy H:mm:ss");
e.ToString("yyyy-dd-MMH:mm:ss");
Also with "/" instead of "-"
Any help here?
The problem isn't with the format of the datetime string; the problem is in the SQL text of the INSERT statement, right before the value is appended. For debugging this, you could output the query string and inspect it.
The problem is in the SQL text here:
+ "', '1,'" +
There needs to be a comma between that literal and the next column value. It looks like you just missed a single quote:
+ "', '1','" +
^
A potentially bigger problem is that your code appears to be vulnerable to SQL Injection. Consider what happens when one of the variables you are including into the SQL text includes a single quote, or something even more nefarios ala Little Bobby Tables. http://xkcd.com/327/.
If you want a column value to be the current date and time, you don't need to run a separate query to fetch the value. You could simply reference the function NOW() in your query text. e.g.
+ "', '1', NOW() )";
You excuted twice
//cmd.ExecuteNonQuery();
DateTime e = (DateTime)cmd.ExecuteScalar();
Should be only one time.
Then like #sgeddes said in the comments use parameterized queries, they avoid errors and sql injections.
The approach that you have used is not the best approach to write SQL command. You should use sql parameters in the Query. Your code is vulnerable to SQL Injected and obviously it is not the best approach.
Try using something like this:
string commandText = "UPDATE Sales.Store SET Demographics = #demographics "
+ "WHERE CustomerID = #ID;";
SqlCommand command = new SqlCommand(commandText, connection);
command.Parameters.Add("#ID", SqlDbType.Int);
command.Parameters["#ID"].Value = customerID;
string sql = "insert into tblmain values('" + txtName.Text + "','" + txtPost.Text + "','" + DropDownList1.SelectedItem + "')";
If the user inserts My name's first later is D ! in txtPost, then it gives error that 's are not allowed.
Can you please send me the code to accept this type of character from textbox in .net (C#).
You sample is the book example of SQL injection in most pure form. ' closes the previous quote and the rest of SQL command is interpreted differently from what you expect.
There is no excuses to not using parametrized queries when dealing with non-hardcoded values and SqlConnection directly.
Also check these articles for mre details. Approximate sample (need more fields and not showing exception handling):
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand("insert into tblmain values(#name")", connection);
command.Parameters.Add("#name", SqlDbType.String);
command.Parameters["#name"].Value = customerID;
connection.Open();
Int32 rowsAffected = command.ExecuteNonQuery();
Console.WriteLine("RowsAffected: {0}", rowsAffected);
}
The second problem you may hit is if you pick wrong field type for the text - to be able to store characters you want you need Unicode string. Check out C#: DbType.String versus DbType.AnsiString post for details.
I am getting the following error
syntax not correct near item number
but I don't see anything wrong, the values being inserted are from a dataset containing field names in variables from another sql query that is being looped through and then inserted into another table like so....
string strOrderDetails =
"INSERT INTO Orders (Order Number, Item Number, Description, Price) " +
"VALUES ('" + strOrderNo.Replace("'", "''").ToString() + "', '"
+ intItemNo + "', '"
+ strDesc.Replace("'", "''").ToString() + "', '"
+ decPrice + "')";
On execution of the above is where the code falls over and states there's an error near the word item number?
Do I need to do something to the intItemNo as it's an integer?
When a column contains spaces you need to enclose it in square brackets or other delimiter for the choosen database
But said that, please do not use string concatenation to build sql commands, but always a parameterized query.
string strOrderDetails = "INSERT INTO Orders ([Order Number], [Item Number]," +
"Description, Price) VALUES (#ordNum, #temNo, #desc, #price";
using(SqlConnection cn = new SqlConnection(conString))
using(SqlCommand cmd = new SqlCommand(strOrderDetails, cn))
{
cn.Open();
cmd.Parameters.AddWithValue("#ordNum",strOrderNo);
cmd.Parameters.AddWithValue("#itemNo",intItemNo);
cmd.Parameters.AddWithValue("#desc",strDesc);
cmd.Parameters.AddWithValue("#price", decPrice);
cmd.ExecuteNonQuery();
}
As you could notice, using parameters remove the need to write code to handle quotes in the input values, but also remove the possibility of Sql Injection attacks
datetime=Datetime.Now;
string strquery = #"INSERT INT0 [Destination_CMS].[dbo].[Destination_CMS_User]
values('" + userid + "','" + email + "','"
+ userType + "','" + userStatus + "','" + processed + "','"
+ datetime.ToLongDateString() + "')";
cmd = new SqlCommand(strquery, con);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
I am getting error:
Incorrect syntax near 'Destination_CMS'.
You've written INT0 rather than INTO.
Also, use parameterized queries.
You should try to change INT0 to INTO.
INSERT INT0 [Destination_CMS].[dbo]
I think its INSERT INTO rather than INT0 (zero)
Print the query to the screen, and verify where the syntax error is.
Next to that; use parametrized queries, like this:
string query = "INSERT INTO [tablename] ( column, column ) VALUES (#p_param1, #p_param2)";
var command = new SqlCommand (query);
command.Parameters.Add ("#p_param1", SqlDbType.DateTime).Value = DateTime.Now;
...
You are risking sql injection, if not using parametrized queries..
Your problem looks solved, so my next question would be, why not use an ORM like NHibernate/EF etc.., depending on your requirements offocourse, but ADO.NET plumbing in my books is where performance is an absolute issue.
You could write this as a stored procedure instead, which has the advantage of making typos like this a lot easier to spot and fix.