I am using a foreach loop to access the values of objects(of type Meal) stored in a list. Then I am calling a database query to save these values into the database .
This is the code I'm using :
foreach (Meal ml in mVals)
{
mID = ml.mealID;
MessageBox.Show(Convert.ToString(mID));
string oString2 = " INSERT into [dbo].[OrderMeal] (orderId,mealId,quantity) " + " VALUES ('" + orderId + "','" + mID + "','" + Convert.ToInt32(quant.Text) + "') ;";
SqlCommand oCmd2 = new SqlCommand(oString2, myConnection);
oCmd2.ExecuteNonQuery();
}
However, this only works for the last value in the list. The next loop iteration seems to be doing the same function, thereby saving the same record, giving an
error of violating the primary key constraint .
Is there some error in the way I am looping through the List?
What the structure of OrderMeal table?
Probably you have primary key in your table, and you need to vetify that you don't duplicate him.
try to enter the value in the list from the sql management.
verify that you don't have special characters in each item in the list( like comma and Apostrophe).
I think you can concatenate a set of insert statement and then ExcuteNonQuery for better performance.
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 made a Table using a Database in visual 2015 and in the table I have name, n1 , n2 , and avg. I made a insert button with 3 textboxes where I insert my name, number1 and number2 and when I press the button I want to save them in a table. If I use 4 textboxes (one for avg) it works, but I want to use a trigger. So.. I created a trigger >
CREATE TRIGGER [Trigger]
ON [dbo].[Table1]
FOR DELETE, INSERT, UPDATE
AS
BEGIN
UPDATE Table1
SET avg = (N1+N2)/2
END
and here is my insert string
string ins = "insert into Table1 values ('"; ins += textBox1.Text + "','" + textBox2.Text + "','" + textBox3.Text + "')";
and I get this error..
Column name or number of supplied values does not match table definition.
I don't know what to do :(
Ok, I still don't think we have all the information, but I'll give a crack at it...
The error message is from the insert statement, not from the trigger.
For your insert, I'd format it so you specifically state which values/columns will be inserted into the table.
It appears as though your average column is a non-nullable field, without a default constraint. So when you try to insert just the 3 values, it wants 4, because it HAS to have 4 (non-nullable). That's why it's throwing the error.
I'd structure your isnert like this:
insert
into Table (Col1, Col2, Col3)
values (val1, val2, val3)
Then, add a default constraint [then updated by trigger], OR, make the Average column nullable, so it can again then be updated via the trigger.
I bet you have a primary key column or another column you're not telling us about.
Either make the Primary Key column Auto-Increment, or make each column allow nulls or give each column a default value.
Also look up SQL Injection as your insert statement is susceptible to attacks.
There is also a problem with your syntax:
string ins = "insert into Table1 values ('"; ins += textBox1.Text + "','" + textBox2.Text + "','" + textBox3.Text + "')";
It should be
string ins = "insert into Table1 values ('" + textBox1.Text + "','" + textBox2.Text + "','" + textBox3.Text + "')";
I'm trying to use a while loop to insert into a table from a List. I want to loop through and write each item from the list by it's index. I'm getting an error with the values I'm trying to insert.
"SQL logic error or missing database near "[y]": syntax error"
while (y < Name.Count)
{
cmd.CommandText = "INSERT INTO Mytable(Column1,Column2) values(Column1[y], Column2[y])";
cmd.ExecuteNonQuery();
y++;
}
Your query is not correct. You need to pass parameters to the query:
"INSERT INTO Mytable(Column1,Column2) values(Column1[#Column1], Column2[#Column1])"
command.Parameters.Add( new SqlParameter( "#Column1", y ) );
Having said that, if I were you, I would use Bulk Insert (or something similar) for this and transfer all the data to the database in one trip.
Your parameters, Column1[y] and Column2[y], are not handled as a index to a data structure but rather as plain text.
cmd.CommandText = "INSERT INTO Mytable(Column1,Column2) values(" + Column1[y] + ", " + Column2[y] + ")";
I have a table which is needed to be updated from a windows form, i am able to update the displayed values into the table where as i am unable to update a particular column where the value to be updated must be a reference value of the displayed data on windows form. The reference value is in another table. Following is the code:
command.CommandText = "INSERT INTO tblComplaints (ComplaintID, Description,ComplaintTypeID,ReceivedDate,ComplaintTypeID)VALUES('" + TextBox7.Text + "','" + TextBox10.Text + "','" + dateTimePicker1.Text + "',???)";
The question mark(???) within the code is what I require.
To be more precise ComplaintTypeName is being displayed in the form in comboBox1 whereas I require its ID to be updated whose values are present in tblComplaintType
Assuming you assigned the ComboBox values somehow like this in advance
ComboboxItem item = new ComboboxItem();
item.Text = "Item text1";
item.Value = 12;
comboBox1.Items.Add(item);
you could do the following:
command.CommandText = "INSERT INTO tblComplaints " +
"(ComplaintID, Description, ComplaintTypeID, ReceivedDate, ComplaintTypeID) " +
"VALUES (#Description,#ComplaintTypeID,#ReceivedDate,#ComplaintTypeID)";
command.Parameters.AddWithValue("#Description", TextBox7.Text);
command.Parameters.AddWithValue("#ComplaintTypeID", TextBox10.Text);
command.Parameters.AddWithValue("#ReceivedDate", dateTimePicker1.Text);
command.Parameters.AddWithValue("#ComplaintTypeID", comboBox1.SelectedValue);
Note that I stripped the ComplaintID from the sql command. Since this is a INSERT statement, you're likely to get a generated ID for that record. If that's not the case you'll have to provide another parameter in the command.
Additionally you should always parameterize your commands instead of building them via string concatenation to prevent sql injection.
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.