string sql = "Insert into tbl_borrowed (FirstName,LastName,BookName,Category,DateBorrowed,Time,DateToBeReturned) values (#fname,#lname,#bname,#category,#dborrow,#time,#dreturn)";
string sql2= "Insert into tbl_return (FirstName,LastName,BookName,Category,DateBorrowed,Time) values (#fname,#lname,#bname,#category,#dborrow,#time";
MySqlCommand sda = new MySqlCommand("", conn);
sda.CommandType = CommandType.Text;
sda.CommandText = sql;
sda.Parameters.AddWithValue("#fname", txtfname.Text);
sda.Parameters.AddWithValue("#lname", txtlname.Text);
sda.Parameters.AddWithValue("#bname", txtbook.Text);
sda.Parameters.AddWithValue("#category", cmbcategory.Text);
sda.Parameters.AddWithValue("#dborrow", dateTimePicker1.Value.Date);
sda.Parameters.AddWithValue("#time", this.time.Text);
sda.Parameters.AddWithValue("#dreturn", dateTimePicker2.Value.Date);
MessageBox.Show("Item has been added!");
showlv("Select * from tbl_borrowed", lvborrowed);
showlv2("Select * from tbl_return", rb.lvreturn);
txtfname.Clear();
txtlname.Clear();
txtbook.Clear();
cmbcategory.Clear();
dateTimePicker1.ResetText();
dateTimePicker2.ResetText();
try
{
conn.Open();
sda.CommandText = sql2;
sda.ExecuteNonQuery();
}
catch (Exception ex)
{
MessageBox.Show("ASDF" + ex);
}
finally
{
conn.Close();
}
I want to insert same values into 2 tables. Im just a beginner, please help me. Bear with me...
ERROR:
In your INSERT query Time is a reserved word and needs to be escaped using backtique like below. BTW, both of your INSERT statement have the same mistake.
Insert into tbl_borrowed (FirstName,LastName,BookName,Category,DateBorrowed,`Time`,DateToBeReturned)
Again, instead of executing multiple INSERT that way it's much better you wrap those queries in a stored procedure and call that procedure from your code. That's way if you needed you can actually have both the INSERT running in the same transaction block by wrapping both of them in a begin trans block.
Related
I have looked around and I am still confused on how to get the last inserted ID. I added the statment SELECT LAST_INSERT_ID(); at the end of mysql statement i am executing. I am storing the value in prID = Convert.ToInt32(cmd.ExecuteScalar()); This command is creating two instances in my database. I am pretty sure I need to separate these two statements but unsure how to while still getting the last ID.
try
{
Console.WriteLine("Connecting to MySQL...");
conn.Open();
string sql = "INSERT INTO pull_requests (repoID, branchID, fileID, prStatus, prComments) VALUES (#rID, #bID, #fID, #prS, #prC); SELECT LAST_INSERT_ID();";
MySql.Data.MySqlClient.MySqlCommand cmd = new MySql.Data.MySqlClient.MySqlCommand(sql, conn);
cmd.Parameters.AddWithValue("#rID", RI);
cmd.Parameters.AddWithValue("#bID", BI);
cmd.Parameters.AddWithValue("#fID", FI);
cmd.Parameters.AddWithValue("#prS", 0);
cmd.Parameters.AddWithValue("#prC", comment);
prID = Convert.ToInt32(cmd.ExecuteScalar());
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
conn.Close();
You need to only call cmd.ExecuteNonQuery() to execute the insert statement. On the return, the cmd object will have its .LastInsertedId property populated for you.
Like this:
try
{
Console.WriteLine("Connecting to MySQL...");
conn.Open();
string sql = "INSERT INTO pull_requests (repoID, branchID, fileID, prStatus, prComments) VALUES (#rID, #bID, #fID, #prS, #prC);";
MySql.Data.MySqlClient.MySqlCommand cmd = new MySql.Data.MySqlClient.MySqlCommand(sql, conn);
cmd.Parameters.AddWithValue("#rID", RI);
cmd.Parameters.AddWithValue("#bID", BI);
cmd.Parameters.AddWithValue("#fID", FI);
cmd.Parameters.AddWithValue("#prS", 0);
cmd.Parameters.AddWithValue("#prC", comment);
cmd.ExecuteNonQuery();
long lastId = cmd.LastInsertedId;
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
conn.Close();
Use the MySqlCommand.LastInsertedId property after executing the query.
Typically, the SELECT last_insert_id() is executed separately, immediately after the INSERT is executed, on the same connection. The result of last_insert_id() is connection specific, so you do not need to worry about other clients "overwriting" yours.
You can even reuse the same command with just cmd.CommandText = "SELECT last_insert_id()";
...but as others have pointed out, and a quick web search has clarified for me, it looks like the MySQL .Net connector you are using already provides that without a second query.
I have a routine where I update the local database with other database data.
I only execute a DELETE and then an INSERT INTO tblX (SELECT * FROM tblY (tblY is a linked table)), as below.
The problem is that, in some cases the SELECT takes a long time after the DELETE and I´d like to diminish the possibility of the user to make a request to this table while it´s processing.
I´d like to know if there is some mechanism to execute the DELETE only after the return of the SELECT.
conn = new OleDbConnection(Conexao.getConexaoPainelGerencialLocal());
conn.Open();
OleDbCommand cmd = new OleDbCommand(" DELETE * FROM tblClienteContato; ", conn);
cmd.ExecuteNonQuery();
cmd = new OleDbCommand(" INSERT INTO tblClienteContato " +
" SELECT * FROM tblClienteContatoVinculada;", conn);
cmd.ExecuteNonQuery();
It sounds like what you need to do is wrap both of those commands in a transaction.
The cool thing about a transaction is that it either ALL WORKS or ALL FAILS, meaning that if something happens to stop the select statement, the database will not finalise the delete statement.
This looks like a really good example to work with:
https://msdn.microsoft.com/en-us/library/93ehy0z8(v=vs.110).aspx
Note that they have one command object, and replace the CommandText, rather than create a new object each time. This is probably important.
Try something like this:
conn = new OleDbConnection(Conexao.getConexaoPainelGerencialLocal());
OleDbCommand cmd = new OleDbCommand();
OleDbTransaction transaction = null;
try {
conn.Open();
transaction = conn.BeginTransaction(IsolationLevel.ReadCommitted);
cmd.Connection = conn;
cmd.Transaction = transaction;
cmd.CommandText = " DELETE * FROM tblClienteContato; ";
cmd.ExecuteNonQuery();
cmd.CommandText = " INSERT INTO tblClienteContato " +
" SELECT * FROM tblClienteContatoVinculada;";
cmd.ExecuteNonQuery();
// The data isn't _finally_ completed until this happens
transaction.Commit();
}
catch (Exception ex)
{
// Something has gone wrong.
// do whatever error messaging you do
Console.WriteLine(ex.Message);
try
{
// Attempt to roll back the transaction.
// this means your records won't be deleted
transaction.Rollback();
}
catch
{
// Do nothing here; transaction is not active.
}
}
You should look into BeginTransaction, Commit and rollback, here's an example:
_con.Open();
_con_trans = _con.BeginTransaction();
using(SqlCommand cmd = _con.CreateCommand())
{
cmd.CommandText = "delete from XXXXX";
cmd.CommandType = CommandType.Text;
cmd.Transaction = _con_trans;
cmd.ExecuteNonquery();
}
using(SqlCommand cmd = _con.CreateCommand())
{
cmd.CommandText = "insert into XXXX";
cmd.CommandType = CommandType.Text;
cmd.Transaction = _con_trans;
cmd.ExecuteNonquery();
}
_con_trans.Commit();
_con_trans = null;
_con.Close();
This way, everything is wrapped under a single transaction, so when the delete begins, the table will be locked for reading and writing.
Without knowing the schema of the table, it is hard to identify why the delete process is taking an extended amount of time.
An alternative to wrapping the commands within a transaction would be to simply delete the table itself rather than the data within it by using the DROP TABLE command. And then you can recreate the table utilizing the SELECT...INTO...FROM statement to recreate. A potential advantage to this is that the schemas will match identically, and any inherent conversions (eg decimal to int) will not need to be done.
using (conn = new OleDbConnection(Conexao.getConexaoPainelGerencialLocal())) {
conn.Open();
using (OleDbCommand cmd = new OleDbCommand()) {
cmd.CommandText = "DROP TABLE tblClienteContato; ";
cmd.ExecuteNonQuery();
cmd.CommandText = "SELECT * INTO tblClienteContato FROM tblClienteContatoVinculada;";
cmd.ExecuteNonQuery();
}
}
The following does not apply here (MS Access), but may to other SQL variants
Another option is to utilize the TRUNCATE command, which will delete everything in the table in one fell swoop. There is no logging of the individual rows and the indexes (if present) don't need to be recalculated on each and every line being deleted. The catch to this method is that this will not work within the transaction. If there is an Identity column the value will be reset as well. There are other potential cons to this but without knowing the design of the table I have no way of identifying them.
using (conn = new OleDbConnection(Conexao.getConexaoPainelGerencialLocal())) {
conn.Open();
using (OleDbCommand cmd = new OleDbCommand()) {
cmd.CommandText = "TRUNCATE TABLE tblClienteContato; ";
cmd.ExecuteNonQuery();
cmd.CommandText = " INSERT INTO tblClienteContato " +
" SELECT * FROM tblClienteContatoVinculada;";
cmd.ExecuteNonQuery();
}
}
As Greg commented, I created temporary tables to receive data from the external database and then I tranfer the data to the definitive tables, so that the probability of the users being impacted is very low.
I am populating a text box with the returned value of a function, but it doesn't work if I run the sql code inside the function. I can remove the sql related code and it works. so i'm stumped.
And by "doesn't work" i mean that the text box never gets populated with anything. it remains blank.
thanks
public string CreateResident()
{
string result = "hmm";
SqlConnection sqlConnection = new SqlConnection("Server=DELLXPS\\SQLEXPRESS; Initial Catalog=Warren_SEINDATASYSTEMS; Integrated Security=true;");
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "INSERT INTO [dbo].[NewUsers]([ResidentAccountNumber],[ResidentName],[ResidentAddress],[NumberOfVisitors],[TempPass],[Role])VALUES(#ResidentAccountNumber,#ResidentName,#ResidentAddress,#NumberOfVisitors,(select cast((Abs(Checksum(NewId()))%10) as varchar(1)) + char(ascii('a')+(Abs(Checksum(NewId()))%25)) + char(ascii('A')+(Abs(Checksum(NewId()))%25)) + left(newid(),5)),'resident')";
cmd.CommandType = CommandType.Text;
cmd.Connection = sqlConnection;
SqlParameter ResidentAccountNumber = new SqlParameter();
ResidentAccountNumber.ParameterName = "#ResidentAccountNumber";
ResidentAccountNumber.Value = txtboxResidenetAccountNumber.Text.Trim();
cmd.Parameters.Add(ResidentAccountNumber);
SqlParameter ResidentName = new SqlParameter();
ResidentName.ParameterName = "#ResidentName";
ResidentName.Value = txtboxResidentName.Text.Trim();
cmd.Parameters.Add(ResidentName);
SqlParameter ResidentAddress = new SqlParameter();
ResidentAddress.ParameterName = "#ResidentAddress";
ResidentAddress.Value = txtboxResidentAddress.Text.Trim();
cmd.Parameters.Add(ResidentAddress);
SqlParameter NumberOfVisitors = new SqlParameter();
NumberOfVisitors.ParameterName = "#NumberofVisitors";
NumberOfVisitors.Value = txtboxNumberOfVisitors.Text.Trim();
cmd.Parameters.Add(NumberOfVisitors);
try
{
sqlConnection.Open();
result = (string)cmd.ExecuteScalar();
sqlConnection.Close();
}
catch (Exception ex)
{
result = ex.Message;
}
return result;
}
protected void btnCreateResident_Click(object sender, EventArgs e)
{
txtboxTempPassword.Text = CreateResident();
}
Your SQL is wrong and you have a lot of problems but I want to show you a way to make your code more readable. Format it like this:
cmd.CommandText = #"INSERT INTO [dbo].[NewUsers] ([ResidentAccountNumber],[ResidentName],[ResidentAddress], NumberOfVisitors],[TempPass], Role])
VALUES(
#ResidentAccountNumber,
#ResidentName,
#ResidentAddress,
#NumberOfVisitors,
(select cast((Abs(Checksum(NewId()))%10) as varchar(1)) + char(ascii('a')+(Abs(Checksum(NewId()))%25)) + char(ascii('A')+(Abs(Checksum(NewId()))%25)) + left(newid(),5)),
'resident')";
cmd.CommandType = CommandType.Text;
cmd.Connection = sqlConnection;
We know that a select in a VALUES constructor is not legal so that is one problem.
Also having a SELECT without a from seems strange -- did you copy your code correctly?
You are using ExecuteScalar -- do you know what that does? It shouldn't include a query that includes INSERT query.
I'm guessing you probably want a stored procedure.
I would suggest do not write query in C# code, you must use Stored Procedure for the same purpose.
If you want your query to return some id, primary key or some value then you must write query for that after your insert query.
you can use the following keywords in your select query,if you want to return id from table.
SCOPE_IDENTITY returns the last IDENTITY value inserted into an IDENTITY column in the same scope.
IDENT_CURRENT returns the last identity value generated for a specific table in any session and any scope.
##IDENTITY returns the last identity value generated for any table in the current session, across all scopes.
If you want to return only one record then use ExecuteScalar else you can use ExecuteReader.
If your only purpose is to insert data into the table then you should use ExecuteNonQuery.
With the help of comments I went with ExecuteReader instead of the ExecuteScaler. And changed the statement to return a value
INSERT INTO [table] ([fields]) OUTPUT Inserted.MyColumn VALUES(values)
C# Code:
reader = cmd.ExecuteReader();
try
{
while (reader.Read())
{
result = reader[0].ToString();
}
}
catch (Exception ex)
{
result = ex.Message;
}
return result;
I'm new in C# programming, so I'll appreciate if anyone can help me. I know there are similar question but I still can't find the solution for my problem. I'm developing a mock system, where when user bought the product, the system will store all the transaction details. the problem is, I cannot insert the data into the database. Here's the code:
using (SqlConnection conn = new SqlConnection
(ConfigurationManager.ConnectionStrings["database"].ConnectionString))
{
string QueryA = "#Insert into TransDetails(AccountNumber,Amount,Provider"
+ ",Mobile Number,TransNum,TransDate, Status) "
+ " Values (#AccountNumber,#Amount,#Provider,#Mobile Number,"
+ "#TransNum,#TransDate,#Status";
using (SqlCommand cmd = new SqlCommand("InsertRecord", conn))
{
conn.Open();
cmd.CommandType = CommandType.Text;
cmd.CommandText = QueryA;
cmd.Parameters.AddWithValue("#AccountNumber", acc.Text);
cmd.Parameters.AddWithValue("#Amount", lblAmount.Text);
cmd.Parameters.AddWithValue("#Provider", lblProvider.Text);
cmd.Parameters.AddWithValue("#Mobile Number", lblNumber.Text);
cmd.Parameters.AddWithValue("#TransNum", lblTrans.Text);
cmd.Parameters.AddWithValue("#TransDate", lblDate.Text);
cmd.Parameters.AddWithValue("#Status", status.Text);
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
catch
{
lblMessage.Text = "Error";
}
finally
{
conn.Close();
}
}
}
and the stores procedures are as follows:
ALTER PROCEDURE InsertRecord1
#AccountNumber int,
#Amount nchar(10),
#Provider nchar(10),
#MobileNumber int,
#TransNum nchar(10),
#TransDate date,
#Status nchar(10)
AS
Insert into TransDetails(AccountNumber,Amount,Provider,MobileNumber,TransNum,TransDate,Status)
Values (#AccountNumber,#Amount,#Provider,#MobileNumber,#TransNum,#TransDate,#Status)
return
Really appreciate any help.
P/S: i dont know why the beginning of the stored procedures started with "alter".
I may be reading it wrong, but it looks like your stored procedure is not used at all. Try commenting out "cmd.CommandText = QueryA;" and substitute "cmd.CommandText = "InsertRecord1";" and change CommandType to StoredProcedure.
QueryA, by the way, is missing a paren at the end. However, the whole thing is unnecessary since you have a stored procedure that does the same thing and it's almost always preferable to use a stored procedure rather than embedded DML.
You must escape Mobile Number while brackets
Insert into TransDetails(AccountNumber,Amount,Provider,[Mobile Number],...
and remove the space in your parameter
...,#MobileNumber,#TransNum,#TransDate,#Status
and change the paramname in your command parameter
cmd.Parameters.AddWithValue("#MobileNumber", lblNumber.Text);
but seeing your stored procedure, the column Mobile Number has no space between it. Is it a typo error in your query on QueryA? If it is, then remove the space on it (also on parameter name)
Insert into TransDetails(AccountNumber,Amount,Provider,MobileNumber,...
or
change your CommandType.Text to CommandType.StoredProcedure and remove this line,
cmd.CommandText = QueryA;
You're using the wrong overload of the SqlCommand constructor. According to MSDN:
new SqlCommand(string, SqlConnection) Initializes a new instance of the SqlCommand class with the text of the query and a SqlConnection.
What you need to do is either set your CommandType for the sql command to CommandType.StoredProcedure and not use QueryA, or initialize the sql command with QueryA and not make use of your stored procedure.
As you can see there is # at the start of your SQL Statement.
Also you are not really using the Store Procedure.
You can Try this:
using (SqlConnection conn = new SqlConnection (ConfigurationManager.ConnectionStrings["database"].ConnectionString))
{
conn.Open();
SqlCommand cmd = new SqlCommand("InsertRecord1", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#AccountNumber", acc.Text);
cmd.Parameters.AddWithValue("#Amount", lblAmount.Text);
cmd.Parameters.AddWithValue("#Provider", lblProvider.Text);
cmd.Parameters.AddWithValue("#Mobile Number", lblNumber.Text);
cmd.Parameters.AddWithValue("#TransNum", lblTrans.Text);
cmd.Parameters.AddWithValue("#TransDate", lblDate.Text);
cmd.Parameters.AddWithValue("#Status", status.Text);
try
{
cmd.ExecuteNonQuery();
}
catch
{
lblMessage.Text = "Error";
}
finally
{
conn.Close();
}
}
Tho I don't use SQL Commands, Adapters...etc. to access the data from the SQL Database. I prefer Microsoft Data Access ApplicationBlocks which is easy-to-use library provided by Microsoft to access data from SQL Server.
Download
You can download it here http://download.microsoft.com/download/VisualStudioNET/daabref/RTM/NT5/EN-US/DataAccessApplicationBlock.msi
Introduction
https://web.archive.org/web/20210304123854/https://www.4guysfromrolla.com/articles/062503-1.aspx
I have made MANY parameterised queries in my time on this lovely planet, and none have thrown an error like this... WTFudge?!?!
ERROR:
There was an error parsing the query. [
Token line number = 1,
Token line offset = 20,
Token in error = #table ]
Obviously the compiler doesn't like my SQL statement... but I see no problem???
Here is my code.
using (SqlCeConnection con = new SqlCeConnection(_connection))
{
string sqlString = "SELECT #colID FROM #table WHERE #keyCol = #key";
SqlCeCommand cmd = new SqlCeCommand(sqlString, con);
cmd.Parameters.Add(new SqlCeParameter("#table", tableName));
cmd.Parameters.Add(new SqlCeParameter("#colID", columnIdName));
cmd.Parameters.Add(new SqlCeParameter("#keyCol", keyColumnName));
cmd.Parameters.Add(new SqlCeParameter("#key", key));
try
{
con.Open();
return cmd.ExecuteScalar();
}
catch (Exception ex)
{
Console.Write(ex.Message);
throw new System.InvalidOperationException("Invalid Read. Are You Sure The Record Exists", ex);
}
finally
{
if (con.State == ConnectionState.Open)
con.Close();
cmd.Dispose();
GC.Collect();
}
}
as you can see its a VERY simple SQL statement. I though "#table" may have been stupidly reserved or something... so ive tried #tableName, #var, #everything!!! dont know what the problem is.
During debug I checked that there was actually a #table parameter in the SqlCeParameterCollection And it was there. Clear as day!!
Since you are in C# (as opposed to stored procs)
string sqlString = "SELECT " + columnIdName +
" FROM " +tableName "WHERE " + keyColumnName + "= #key";
You will want to verify that columnIdName, tableName, keyColumnName are all restricted to a list of values (or at the very least, restrict the length to, say 50 characters), otherwise this procedure is optimized for insecurity and sql injection attacks.
This affected me too on SqlCe. But in Sql Server and in SqlExpress you can use a paarameter for table name.