I have a database with some columns named UPC title Description and Quantity. i am trying to do a check to see if a UPC number already exists in the column and IF IT DOES then update the quantity of that entry by 1 here is what i have so far:
MySqlConnection connection = new MySqlConnection(MyConString);
connection.Open();
MySqlCommand command = connection.CreateCommand();
command.CommandText = "INSERT INTO tableName " +
"(upc, title, description, quantity) " +
"VALUES " +
"(#upc, #title, #description, #quantity)";
MySqlCommand upcCheck = connection.CreateCommand();
upcCheck.CommandText = "Select COUNT (*) FROM tableName WHERE " +
"(upc=#upc) LIMIT 1";
upcCheck.Parameters.AddWithValue("#upc", upc.Text); //Checks for duplicate UPCs
MySqlDataReader check = upcCheck.ExecuteReader();
if( check.Read() != false)
{
command.Parameters.AddWithValue("#quantity",++); //not sure how to word it right
}
command.Parameters.AddWithValue("#upc", upc.Text); //adding parameters SAFELY to the statement
command.Parameters.AddWithValue("#title", titlename);
command.Parameters.AddWithValue("#description", descname);
command.Parameters.AddWithValue("#quantity", "1");
MySqlDataReader result = command.ExecuteReader();
I'm just not sure how to word it to do the check.
UPDATE! Here is the working code.
MySqlConnection connection = new MySqlConnection(MyConString);
connection.Open();
MySqlCommand updatecommand = connection.CreateCommand();
updatecommand.CommandText = "UPDATE tableName Set quantity = quantity +1 " +
"WHERE upc = #upc";
updatecommand.Parameters.AddWithValue("#upc", upc.Text);
using (MySqlDataReader updateResult = updatecommand.ExecuteReader())
{
if (updateResult.RecordsAffected == 0)
{
affected = true;
}
else
{
affected = false;
}
}
if(affected == true)
{
MySqlCommand command = connection.CreateCommand();
command.CommandText = "INSERT INTO tableName " +
"(upc, title, description, quantity) " +
"VALUES " +
"(#upc, #title, #description, #quantity)";
command.Parameters.AddWithValue("#upc", upc.Text);
command.Parameters.AddWithValue("#title", titlename);//adding parameters SAFELY to the statement
command.Parameters.AddWithValue("#description", descname);
command.Parameters.AddWithValue("#quantity", "1");
MySqlDataReader result = command.ExecuteReader();
}
Although I've not worked specifically with MySqlDataReader, I would slightly change the queries around... the otherwise format (parameterization) you have for the insert is completely fine.
Although the ON DUPLICATE KEY UPDATE provided by Hristo is cool, you would be missing the other column elements for your record. I would change to..
MySqlCommand command = connection.CreateCommand();
command.CommandText = "UPDATE tableName Set Quantity = Quantity +1 " +
"WHERE upc = #upc"
command.Parameters.AddWithValue("#upc", upc.Text);
** Dont know how the value / status will be returned from the MySqlDataReader, but
result = command.ExecuteReader();
if( the status indicates it actually succeeded in an update,
or how many records were updated > 0 )
return; // you've just increased the counter...
OTHERWISE, it was not on file.. continue with the rest of your SQL-insert command, we can overwrite the last command instance...
command = connection.CreateCommand();
command.CommandText = "INSERT INTO tableName " +
"(upc, title, description, quantity) " +
"VALUES " +
"(#upc, #title, #description, #quantity)";
command.Parameters.AddWithValue("#upc", upc.Text);
command.Parameters.AddWithValue("#title", titlename);
command.Parameters.AddWithValue("#description", descname);
command.Parameters.AddWithValue("#quantity", "1");
result = command.ExecuteReader();
If UPC is you primary key you can use INSERT ON DUPLICATE KEY UPDATE functionality of MySQL database. If you dont want to INSERT the new UPC just run an UPDATE query if there is no such row if wont affect the data in the table.
UPDATE <tablename> SET quantity=quantity+1 WHERE UPC='<upc>'
Related
Column names in each table must be unique. Column name 'Delivery' in table 'Sales' is specified more than once.
How can I solve this? I get a System.Data.SqlClient.SqlException.
class DataAccess
{
string ConnectionString;
public DataAccess()
{
ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["CafeteriaDBConnectionString"].ConnectionString;
}
public bool RecordASale(ArrayList ProductsList, DateTime SaleTime, int SalesmanID, decimal CashGiven, decimal TotalBill, decimal CashReturn, string Delivery)
{
int SaleID = ReturnSaleID();
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand("alter table [Sales] add [Delivery] varchar default 5 NOT NULL"))
{
command.Connection = connection;
command.ExecuteNonQuery();
}
}
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
connection.Open();
/*Start a local transaction*/
SqlTransaction sqlTran = connection.BeginTransaction();
/*Enlist a command in the current transaction*/
SqlCommand command = connection.CreateCommand();
command.Transaction = sqlTran;
try
{
// Execute separate commands.
command.Parameters.AddWithValue("#SaleTime", SaleTime);
command.Parameters.AddWithValue("#SalesmanID", SalesmanID);
command.Parameters.AddWithValue("#CashGiven", CashGiven);
command.Parameters.AddWithValue("#TotalBill", TotalBill);
command.Parameters.AddWithValue("#CashReturn", CashReturn);
/*command.Parameters.AddWithValue("#Delivery", Delivery);*/
command.CommandText =
"Insert into Sales (SaleTime, SalesmanID, CashGiven, TotalBill, CashReturn, Delivery) values (#SaleTime, #SalesmanID, #CashGiven, #TotalBill, #CashReturn, #Delivery)";
command.ExecuteNonQuery();
foreach (Details ProductDetail in ProductsList)
{
//// Execute separate commands.
//command.Parameters.AddWithValue("#ProductName", ProductDetail.Name);
//command.Parameters.AddWithValue("#ProductPrice", ProductDetail.Price);
//command.Parameters.AddWithValue("#ProductQuantity", ProductDetail.Quantity);
//command.Parameters.AddWithValue("#ProductTotal", ProductDetail.Total);
//command.Parameters.AddWithValue("#SaleID", SaleID);
command.CommandText =
"Insert into SaleItems (ProductName, ProductPrice, ProductQuantity, ProductTotal, SaleID) values ('" + ProductDetail.Name + "', '" + ProductDetail.Price + "', '" + ProductDetail.Quantity + "', '" + ProductDetail.Total + "', '" + SaleID + "')";
command.ExecuteNonQuery();
}
// Commit the transaction.
sqlTran.Commit();
//connection.Close();
return true;
}
catch (Exception ee)
{
throw ee;
}
}
}
If you want to check if your column exists before adding it to the datatable you should change your code in this way
string sql = #"if NOT exists(SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS
WHERE Column_Name = 'Delivery' AND Table_Name = 'Sales')
ALTER TABLE Sales ADD Delivery VARCHAR DEFAULT 5 NOT NULL";
using (SqlCommand command = new SqlCommand(sql))
{
command.Connection = connection;
command.ExecuteNonQuery();
}
In this way the operation to add the column Delivery to he table Sales will be executed only if the query on INFORMATION_SCHEMA.COLUMNS doesn't return a value
I have also noticed now that you are building your INSERT command concatenating strings together. This is a well know security problem that you can learn about searching how one can use it for Sql Injection
Also, if the SalesID column is an Identity column, you should not try to pass a value for it in the sql query
If I put "if, foreach, and else statement under comment //", the program works and Reduces book count by 1 from SQL database. But I want to check IF there is at least 1 available book to give. This code keeps showing me the message in "else" statement if I leave it like this. Help is needed fast, it's my final project, that is needed to be done before 23.07. :(
int book_qty = 0;
SqlCommand cmd2 = connection.CreateCommand();
cmd2.CommandType = CommandType.Text;
cmd2.CommandText = "SELECT * FROM Book_list WHERE BookName = '" + TextBoxBookName + "'";
cmd2.ExecuteNonQuery();
DataTable dt2 = new DataTable();
SqlDataAdapter da2 = new SqlDataAdapter(cmd2);
da2.Fill(dt2);
foreach (DataRow dr2 in dt2.Rows)
{
book_qty = Convert.ToInt32(dr2["book_qty"].ToString());
}
if (book_qty > 0)
{
SqlCommand cmd = connection.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "INSERT INTO Issue_book VALUES(" + TextBoxSearchMembers.Text + ",'" + TextBoxMemberName.Text + "','" + TextBoxMemberContact.Text + "','" + TextBoxMemberEmail.Text + "','" + TextBoxBookName.Text + "', '" + DateTimePicker1.Text + "')";
cmd.ExecuteNonQuery();
SqlCommand cmd1 = connection.CreateCommand();
cmd1.CommandType = CommandType.Text;
cmd1.CommandText = "UPDATE Book_list SET BookAvailability = BookAvailability-1 WHERE BookName ='" + TextBoxBookName.Text + "'";
cmd1.ExecuteNonQuery();
MessageBox.Show("successful issue");
this.Close();
else
{
MessageBox.Show("Book not available");
}
You are only checking book_qty from the last row in your result set instead of BookAvailability for all rows. You probably want to do something like:
SqlCommand cmd2 = connection.CreateCommand();
cmd2.CommandType = CommandType.Text;
cmd2.CommandText = "SELECT BookAvailability FROM Book_list WHERE BookName = '" + TextBoxBookName + "'";
var result = cmd2.ExecuteScalar();
book_qty = Convert.ToInt32(result);
You need to make sure that there is only one book with the given bookname available.
In that case just correcting this one line in your code would help as well:
book_qty = Convert.ToInt32(dr2["book_qty"].ToString());
to
book_qty = Convert.ToInt32(dr2["BookAvailability"].ToString());
Otherwise you'd need to query SUM(BookAvailability), but the following code would decrease the amount of books for multiple books at once, that wouldn't be good.
Untested code. I don't have your database. Comments and explanation in line.
private void OPCode()
{
try
{
//keep your connections close to the vest (local)
using (SqlConnection connection = new SqlConnection())
//a using block ensures that your objects are closed and disposed
//even if there is an error
{
using (SqlCommand cmd2 = new SqlCommand("SELECT BookAvailability FROM Book_list WHERE BookName = #BookName", connection))
{
//Always use parameters to protect from sql injection
//Also it is easier than fooling with the single quotes etc.
//If you are referring to a TextBox you need to provide what property is
//being accessed. I am not in a WPF right now and not sure if .Text
//is correct; may be .Content
//You need to check your database for correct data type and field size
cmd2.Parameters.Add("#BookName", SqlDbType.VarChar, 100).Value = TextBoxBookName.Text;
//A select statement is not a non-query
//You don't appear to be using the data table or data adapter
//so dump them extra objects just slow things dowm
connection.Open();
//Comment out the next 2 lines and replaced with
//Edit Update
//var returnVal = cmd2.ExecuteScalar() ?? 0;
//if ((int)returnVal > 0)
//*************************************************************
//Edit Update
//*************************************************************
//in case the query returns a null, normally an integer cannot
//hold the value of null so we use nullable types
// the (int?) casts the result of the query to Nullable of int
Nullable<int> returnVal = (int?)cmd2.ExecuteScalar();
//now we can use the .GetValueOrDefault to return the value
//if it is not null of the default value of the int (Which is 0)
int bookCount = returnVal.GetValueOrDefault();
//at this point bookCount should be a real int - no cast necessary
if (bookCount > 0)
//**************************************************************
//End Edit Update
//**************************************************************
{
using (SqlCommand cmd = new SqlCommand("INSERT INTO issue_book VALUES(#SearchMembers etc", connection))
{
//set up the parameters for this command just like the sample above
cmd.Parameters.Add("#SearchMembers", SqlDbType.VarChar, 100).Value = TextBoxSearchMembers.Text;
cmd.ExecuteNonQuery();
}
using (SqlCommand cmd1 = new SqlCommand("UPDATE Book_list SET BookAvailability = BookAvailability-1 WHERE BookName = #BoxBookName;", connection))
{
cmd1.Parameters.Add("#BoxBookName", SqlDbType.VarChar, 100);
cmd1.ExecuteNonQuery();
}
MessageBox.Show("success");
this.Close();
}
else
{
MessageBox.Show("Book not available");
}
}
}
}
catch (Exception exc)
{
MessageBox.Show(exc.ToString());
}
}
I am trying to first create a new row in my SQL Compact Edition database via C# and then I want to update the same row with information in my radiobuttons. I have an "ID" column in the database which is auto incremental.
So I tried to assign its value to a variable using ##Identity and call it in the update query but it doesn't work. I've tried MAX to find the max value in ID column which will be the latest row but it still didn't work. Here's my code.
con.Open();
string sqlAdd = "Insert into MembersTable ([First Name],Surname,[Middle Name])
Values('"+txtFirstName.Text+"','"+txtSurname.Text+"','"+ txtMiddleName.Text+"')";
string IDIdentifier = "Select ##Identity AS TempID";
string sqlgenderM = "Update MembersTable set Gender='M' where ID='" + DC.ID + "'";
string sqlgenderF = "Update MembersTable set Gender='F' where ID='" + DC.ID + "'";
com = new SqlCeCommand(sqlAdd, con);
com.ExecuteNonQuery();
SqlCeCommand com1 = new SqlCeCommand(IDIdentifier, con);
SqlCeDataReader dr1 = com1.ExecuteReader();
if (dr1.Read())
{
DC.ID = dr1["TempID"].ToString();
}
{
if (rbGenderMale.Checked == true)
{
SqlCeCommand gendercom = new SqlCeCommand(sqlgenderM, con);
gendercom.ExecuteNonQuery();
}
else if (rbGenderFemale.Checked == true)
{
SqlCeCommand gendercom = new SqlCeCommand(sqlgenderF, con);
gendercom.ExecuteNonQuery();
}
}
The fields (First Name, Middle Name, Surname) get updated but the Gender columns don't. What am I doing wrong?
Thanks to #Soner I used:
int.TryParse(dr1["TempID"].ToString(), out Identity);
string IdentityS = Identity.ToString();
and replaced DC.ID with IdentityS
Now it works perfectly.
I want to check if record exists or not if it exists i dont want to insert if it bot i want to insert the data in ms access database in c#.
OleDbCommand cmd = new OleDbCommand("insert into MyTable values('" + test + "','" + test + "','" + "123" + "');", con);
OleDbCommand cmd1 = new OleDbCommand("select * from MyTable", con);
temp = 0;
try
{
con.Open();
string count = (string)cmd1.ExecuteScalar();
temp = cmd.ExecuteNonQuery();
if (temp > 0)
{
MessageBox.Show("One Record Added");
}
else
{
MessageBox.Show("Record not added");
}
}
catch
{ }
Can Anyone suggest me some code.
Thanks In Advance.
Filter your Select query on the basis of some key . Check if it returns for existence or non-existence of the particular record and do the processing required .
string cmdStr = "Select count(*) from MyTable where id = 1"; //get the existence of the record as count
OleDbCommand cmd = new OleDbCommand(cmdStr, conn);
int count = (int)cmd.ExecuteScalar();
if(count >0)
{
//record already exist
}
Modify this line
OleDbCommand cmd1 = new OleDbCommand("select * from MyTable", con);
I am trying to insert a record and get its newly generated id by executing two queries one by one, but don't know why its giving me the following error.
Object cannot be cast from DBNull to other types
My code is as below: (I don't want to use sql stored procedures)
SqlParameter sqlParam;
int lastInsertedVideoId = 0;
using (SqlConnection Conn = new SqlConnection(ObjUtils._ConnString))
{
Conn.Open();
using (SqlCommand sqlCmd = Conn.CreateCommand())
{
string sqlInsertValues = "#Name,#Slug";
string sqlColumnNames = "[Name],[Slug]";
string sqlQuery = "INSERT INTO videos(" + sqlColumnNames + ") VALUES(" + sqlInsertValues + ");";
sqlCmd.CommandText = sqlQuery;
sqlCmd.CommandType = CommandType.Text;
sqlParam = sqlCmd.Parameters.Add("#Name", SqlDbType.VarChar);
sqlParam.Value = txtName.Text.Trim();
sqlParam = sqlCmd.Parameters.Add("#Slug", SqlDbType.VarChar);
sqlParam.Value = txtSlug.Text.Trim();
sqlCmd.ExecuteNonQuery();
//getting last inserted video id
sqlCmd.CommandText = "SELECT SCOPE_IDENTITY() AS [lastInsertedVideoId]";
using (SqlDataReader sqlDr = sqlCmd.ExecuteReader())
{
sqlDr.Read();
lastInsertedVideoId = Convert.ToInt32(sqlDr["lastInsertedVideoId"]);
}
}
}
//tags insertion into tag table
if (txtTags.Text.Trim().Length > 0 && lastInsertedVideoId > 0)
{
string sqlBulkTagInsert = "";
string[] tags = txtTags.Text.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
foreach (string tag in tags)
{
sqlBulkTagInsert += "INSERT INTO tags(VideoId, Tag) VALUES(" + lastInsertedVideoId + ", " + tag.Trim().ToLowerInvariant()+ "); ";
}
using (SqlConnection Conn = new SqlConnection(ObjUtils._ConnString))
{
Conn.Open();
using (SqlCommand sqlCmd = Conn.CreateCommand())
{
string sqlQuery = sqlBulkTagInsert;
sqlCmd.CommandText = sqlQuery;
sqlCmd.CommandType = CommandType.Text;
sqlCmd.ExecuteNonQuery();
}
}
}
And also if possible, please check is the above code coded well or we can optimize it more for improve performance?
Thanks
The call to SCOPE_IDENTITY() is not being treated as being in the same "scope" as the INSERT command that you're executing.
Essentially, what you need to do is change the line:
string sqlQuery = "INSERT INTO videos(" + sqlColumnNames + ") VALUES(" + sqlInsertValues + ");";
to:
string sqlQuery = "INSERT INTO videos(" + sqlColumnNames + ") VALUES(" + sqlInsertValues + "); SELECT SCOPE_IDENTITY() AS [lastInsertedVideoId]";
and then call
int lastVideoInsertedId = Convert.ToInt32(sqlCmd.ExecuteScalar());
instead of .ExecuteNonQuery and the code block following the "//getting last inserted video id" comment.
The SCOPE_IDENTITY() should be extracted from the first command (SELECT, RETURN or OUT) and passed into the next command. By that, I mean that the SELECT_IDENTITY() should be at the end of the first command. In SQL 2008 there is additional syntax for bring values back as part of the INSERT, which makes this simpler.
Or more efficiently: combine the commands into one to avoid round-trips.