Query working fine in SQL but not in the code - c#

I have a simple query updating the ProductPrice column by replacing old data and updating ProductQuantity which is being added to the previous one.
I wrote the query in SQL and it's working fine, but in the VS code it's concatenating the ProductQuantity. Like if I have 20 in product quantity then after this the result should be 20 + 50 = 70 but after executing query in code it updates the value to 2050
The query in SQL is:
UPDATE ProductLog
SET ProductQuantity = ProductQuantity + 50,
ProductPrice = 20
WHERE ProductCode = 1
The query in my C# code is:
sql = "";
sql += "UPDATE ProductLog
SET ProductQuantity = ProductQuantity
+ '"
+ productQuantity
+ "', ProductPrice = '"
+ productPrice
+ "' WHERE ProductCode = '"
+ ProductCode
+ "'";
I am not able to find my mistake in code query. Please guide me in this regard.
The column's datatype in the table is varchar.

Jack,
That is because when you are manually generating a query via string concatenation, it will not add the numeric values together. It will run all your variables through their respective .ToString() methods, get the result, and concatenate the result into your string. Depending on how you are executing this query (ADO.NET, Linq2SQL, or Entity Framework) you are better off using the mechanisms in those technologies to update your values as opposed to manually creating those strings. If you want to continue doing this way you will have to retrieve the value for "ProductQuantity", add that value to 50 (or whatever value you want) and then do the concatenation before executing the query.

Related

How do I make a foreign key in one of my databases copy the primary key that it is referencing to while I create a record? [duplicate]

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();

Setting SQL query parameter to Int32 in C#

I'm having problems with some code I'm trying to write. I'm doing something for suppliers orders, so I have a table which is named "encomendas_fornecedores" with a autoincrement field before the key that is the code of sale which consists in a EF before the number(which is a text field).
Here is the code:
connection.Open();
OleDbCommand comando1 = new OleDbCommand();
OleDbCommand comando2 = new OleDbCommand();
OleDbCommand comando3 = new OleDbCommand();
comando1.Connection = connection;
comando2.Connection = connection;
comando3.Connection = connection;
comando1.CommandText = "INSERT INTO encomendas_fornecedores (cod_encomenda_forn, cod_metodo, cod_forn, total_pagar_forn) VALUES('FO', '" + txtcodmetodo.Text + "', '" + txtcodforn.Text + "', '" + lbltotalapagar.Text + "'); ";// insert into table the values with a FO to cod
comando1.ExecuteNonQuery();
comando2.CommandText = "Select MAX(num_encomenda) From encomendas_fornecedores;";// selecting maximum num encomenda so I can isolate it and add to a text before(btw I do this in php/sql no problems
int numero = Convert.ToInt32(comando2.ExecuteScalar());//max num_encomenda
string codencomendaforn= "EF"+Convert.ToString(numero);// sales code completed
comando3.CommandText = "UPDATE encomendas_fornecedores SET cod_encomenda_forn = '"+codencomendaforn+"' WHERE num_encomenda = '"+ numero +"';";//query that is giving me the problems, it says something like "type of data incorrect in data expression"
comando3.ExecuteScalar();//giving me error this line
connection.Close();
But now here's the catch the cod_encomenda_forn is text and the num_encomenda auto increment as it is in the sql, and I tried to show the query in a textbox to see if its anything is wrong but nothing seems wrong.
"UPDATE encomendas_fornecedores SET cod_encomenda_forn = '"+codencomendaforn+"' WHERE num_encomenda = **'**"+ **numero** +"**'**;";//query that is giving me the problems,it says something like "type of data incorrect in data expression"
You are passing a string numero to a where statement that seems like it is expecting a number. As long as it is numeric it should work, but definitely not gauranteed to work. Second you are passing anothercodencomendaforn string to encomenda what is encomenda 's data type?
It appears that you are not handling potential datatype differences between your c# code and your SQL query. In addition single quoting '' around a value in a SQL statement tells the database engines that it is a string even if that is '1234'. While SQL will automatically convert some values it doesn't always. In addition c# .net library also looks for some conversion etc. before sending the SQL statement. To fix appropriately use parameters that are data typed to the database type in the SQL table. To fix it simply in the statement figure out your data types and fix the '' single quotes appropriately.
PS the people trying to help you in the comments were being nice and telling you the professional way of keeping your job in the future when you graduate after fixing this issue.

Delete an access file row via DataGrid

I'm currently learning to delete and update files into an access database (mdb).
But i encountered an error which i'm not able to solve.
My database consists of 6 columns. The relevant columns for now are "ID" and "Date". ID is a textfield with an autoincrement primary key and date an ordinary text field (dd.MM.yyyy).
I can delete rows by selecting an ID just fine. (The selecting is done by putting the ID into a textfield)
Now i wanted to get rid of the whole ID since i don't really need it in the database itself and wanted to select the rows by the actual Date (which only exists once).
But if i try to select by date i encounter a
Syntaxerror in number in query expression 'Date =29.10.201'
I'm not sure why the 2015 gets shortened so instead of using "dateTimePicker1.Text" i converted the dateTimePicker value to string and split it, then returned only the Date but it gets the same error.
Here is the code i used for the split:
string date = dateTimePicker1.Value.ToString().Split(' ')[0];
con.Open();
OleDbCommand command = new OleDbCommand();
command.Command.Text = "delete from " + user + " where Date =" + date + " ";
command.ExecuteNonQuery;
con.Close();
And here is the code i used before
command.Command.Text = "delete from " + user + " where Date =" + dateTimePicker1.Text + " ";
Thanks in advance for every answer. :)
A literal date needs to be escaped just like a string i.e. ... WHERE Date = '2015-10-29'. Ensure the format of the date in your SQL command as well.
Have you inspected command.Command.Text before you call ExecuteNonQuery ?

Nested Insert Into Errors

I've created this Insert Into SQL query, it takes information from the table lessons where the text box containing the lesson ID matches with any of the lessons. I have tested this Query works as it returns the correct values to a datagrid view in.
The second part of the query is supposed to get the student ID and Student Name from the text box that the user has input information. Then transfer this into the Less/Stud table.
This table has a the following Columns
Lesson Name Lesson ID Student ID Student Name Optional?
I do not need to worry about the Optional column as that is a check box not needed yet, below is the current query that doesnt work. It returns the following errors:
Incorrect Syntax near '/'
Incorrect Syntax near 'Test Student Name'
The second error within the ' ' always contains the information from the student name text box.
INSERT INTO Less/Stud ([LessonName],[Lesson ID],[Student ID],[Student Name])
SELECT LessonName, LessonID
FROM Lessons
WHERE ClassID ='" + txtClassID.Text + "'
AND (SELECT [Student ID], [StudentName]
'" + txtStuId.Text + "', '" + txtName.Text + "' "
You need to put all four columns being inserted in the outer select:
INSERT INTO Less/Stud ([LessonName],[Lesson ID],[Student ID],[Student Name])
SELECT LessonName, LessonID, '" + txtStuId.Text + "', '" + txtName.Text + "' "
FROM Lessons
WHERE ClassID ='" + txtClassID.Text + "'
There are two errors in your query.
If your table is Less/Stud then you must call the table name with square brackets like [Less/Stud]
Your Insert query have 4 columns but your SELECT query have only 2 columns. Thats also must be changed.
And the most important one, your query is prone to SQL injection. Try to use parameterized query.
Is "Less/Stud" your table name? I would suggest putting that in quotes, because the / seems to be confusing the database.
The WHERE clause also seems to be incomplete. A subselection is being started, but never completed.
You should also only put the fields you actually want to insert data into in the first line. Since you only provide 2 values in the SELECT clause, you can not define 4 fields to insert into.
EDIT: It turns out you want to insert values from a textbox into the Student ID and Student Name fields, based on your clarification. I have altered my suggested query to reflect this. I have not been able to test this, so I might have some mismatching quotes here and there, but I think it should be something like this:
"INSERT INTO [Less/Stud] ([LessonName],[Lesson ID],[Student ID],[StudentName])
SELECT LessonName
, LessonID
, '" + txtStuId.Text + "'
, '" + txtName.Text + "'
FROM Lessons
WHERE ClassID ='" + txtClassID.Text + "' "
You might want to consider using the String.Format() method to put the textbox values into the SQL string though. I personally think the string would be more readable that way. It would look like this:
var yourQuery = String.Format(
"INSERT INTO [Less/Stud] ([LessonName],[Lesson ID],[Student ID],[StudentName]) SELECT LessonName, LessonID, '{0}', '{1}' FROM Lessons WHERE ClassID ='{2}' "
, txtStuId.Text
, txtName.Text
, txtClassId.Text
);
Breaking up the SQL statement itself into multiple lines might also be a good idea, especially for even longer and/or more complicated statements.

Update DATETIME column where said DATETIME < current DATETIME

I've got an ASP.NET 4.0 C# web application that allows multiple users to update rows in the SQL Server DB at the same time. I'm trying to come up with a quick system that will stop USER1 from updating a row that USER2 updated since USER1's last page refresh.
The problem I'm having is that my web application always updates the row, even when I think it shouldn't. But when I manually run the query it only updates when I think it should.
This is my SQL query in C#:
SQLString = "update statuses set stat = '" + UpdaterDD.SelectedValue +
"', tester = '" + Session["Username"].ToString() +
"', timestamp_m = '" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") +
"' where id IN (" + IDs + ") and timestamp_m < '" + PageLoadTime + "';";
And here's a 'real world' example:
SQLString = "update statuses set stat = 'PASS', tester = 'tester007',
timestamp_m = '2013-01-23 14:20:07.221' where id IN (122645) and
timestamp_m < '2013-01-23 14:20:06.164';"
My idea was that this will only update if no other user has changed this row since the user last loaded the page. I have formatted PageLoadTime to the same formatting as my SQL Server DB, as you can see with DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), but something still isn't right.
Does anyone know why I get two different results? Is what I want to do even possible?
I really think the problem is that the page load time is not being set correctly, or is being set immediately before the DB call. For debugging, you may try hardcoding values into it that you know will allow or disallow the insert.
Here's a parameterized version of what you have. I also am letting the DB server set the timestamp to its current time instead of passing a value. If your DB server and your Web server may not have their time of day in synch, then set it yourself.
Using parameterization, you don't have to worry about whether the date/time format is correct or not. I don't know what the DB types are of stat, tester, and timestamp_m so adding the parameter DB type may need adjusting.
string sql = "update statuses set stat = #stat, tester = #tester" +
", timestamp_m = getdate()" +
" where id IN (" + IDs + ") and timestamp_m < #pageLoadTime";
SQLConnection conn = getMeASqlConnection();
SQLCommand cmd = new SQLCommand(sql, conn);
cmd.Parameters.Add("#stat", System.Data.SqlDbType.NVarChar).Value = UpdaterDD.SelectedValue;
cmd.Parameters.Add("#tester", System.Data.SqlDbType.NVarChar).Value = Session["Username"].ToString();
// Here, pageLoadTime is a DateTime object, not a string
cmd.Parameters.Add("#pageLoadTime", System.Data.SqlDbType.DateTime).Value = pageLoadTime;

Categories