I am new to SQL, I have table with RecordId that is incremented automatically and is primary key. I would like to get RecordId of the row that was inserted into table.
Thanks in advance for help.
myCommand.CommandText = "INSERT INTO " + tableName + " (DateRaised,RaisedBy,WeekNo,Platform,Department,Site,Process, Area,NavErrorNo,RootCauseDescription,Status) " +
"VALUES ('" + currentDate.ToString(format) + "','" +
sender + "'," +
weekNumber + ",'" +
comboBoxPlatform.SelectedItem + "','" +
comboBoxDepartment.SelectedItem + "','" +
comboBoxSite.SelectedItem + "','" +
comboBoxProcess.SelectedItem + "','" +
comboBoxArea.SelectedItem + "','" +
textBoxNavError.Text + "','" +
textBoxIssue.Text + "','Open')";
//int lastInsertedId =
myCommand.ExecuteNonQuery();
lastInsertedId should be int from RecordId in my table.
To do this properly (if this is for SQL Server - you weren't very clear on this), I see two options:
Approach #1 - using SCOPE_IDENTITY
This works well if you're only ever inserting a single row at a time - use something like this:
// set up your query using *PARAMETERS** as you **ALWAYS** should!
// Using SELECT SCOPE_IDENTITY() to get back the newly inserted "Id"
myCommand.CommandText = "INSERT INTO dbo.SomeTable (list-of-columns) " +
"VALUES (#param1, #param2, #param3, ...., #paramN); " +
"SELECT SCOPE_IDENTITY();";
// set up the parameters and theirs values
object result = myCommand.ExecuteScalar();
if (result != null)
{
int lastInsertedId = Convert.ToInt32(result);
}
Approach #2 - using the OUTPUT clause
This works well even if you insert multiple rows at once (typically using a SELECT after the INSERT):
// set up your query using *PARAMETERS** as you **ALWAYS** should!
// Using SELECT SCOPE_IDENTITY() to get back the newly inserted "Id"
myCommand.CommandText = "INSERT INTO dbo.SomeTable (list-of-columns) " +
"OUTPUT Inserted.RecordId " +
"VALUES (#param1, #param2, #param3, ...., #paramN); ";
// set up the parameters and theirs values
object result = myCommand.ExecuteScalar();
if (result != null)
{
int lastInsertedId = Convert.ToInt32(result);
}
First thing this is not a good idea to call direct SQL statement from code it can cause an issue for SQL injection as #Zohar suggested.
You can either user parametrized query or sp.
Inside sp, you can use
SELECT ##IDENTITY AS 'Identity';
after Insert statement, it will return the last auto-incremented value for PK,
then return this value as an output parameter and catch it after .ExecuteNonQuery(); in C# code.
This should do the trick for You
private void SelectLast()
{
string sqlLast = "SELECT TOP(1) RecordId FROM [YourtableName] ORDER BY 1 DESC";
Connection.Open();
using (SqlCommand cmd = new SqlCommand(sqlLast, Connection))
{
cmd.CommandType = CommandType.Text;
{
int insertedID = Convert.ToInt32(cmdAdd.ExecuteScalar());
textBoxID.Text = Convert.ToString(insertedID);
}
Connection.Close();
}
}
Related
There is no error in this code. The only concern I face is when I try to save in the database the FK won't get the id of PK. I already setup my database relationship and it connect id - projectid.
if (textID.Text == "" && textProject.Text == "" && textAmount.Text == "")
{
MessageBox.Show("Please Enter Details..!");
}
else
{
SqlDataAdapter adapter = new SqlDataAdapter("SELECT * FROM tbl_project WHERE Contract_ID = '" + textID.Text + "'", conn);
DataTable datatbl = new DataTable();
adapter.Fill(datatbl);
if (datatbl.Rows.Count == 1)
{
MessageBox.Show("Contract ID Already Exist!!");
}
else
{
SqlDataAdapter adap1 = new SqlDataAdapter("INSERT INTO tbl_project(Contract_ID,Contract_Amount,Contractor,Project_Name,Start_Date,End_Date,Year,Address,Remarks,Status)VALUES('" + textID.Text + "','" + textAmount.Text + "','" + textContract.Text + "','" + textProject.Text + "','" + dateTimePicker1.Value.Date + "','" + dateTimePicker2.Value.Date + "','" + textYear.Text + "','" + textAddress.Text + "','" + textOthers.Text + "','" + comboBox5.Text + "')", conn);
DataTable fill1 = new DataTable();
adap1.Fill(fill1);
SqlDataAdapter adap2 = new SqlDataAdapter("INSERT INTO tbl_expense(CONTRACT,CONTRACT_ID,CONTRACTOR,PROJECT_STATUS,COVERED_PERIOD,END_PERIOD,PROJECT_AMOUNT)VALUES('" + textProject.Text + "','" + textID.Text + "','" + textContract.Text + "','" + comboBox5.Text + "','" + dateTimePicker1.Value.Date + "','" + dateTimePicker2.Value.Date + "','" + textAmount.Text + "')", conn);
DataTable data2 = new DataTable();
adap2.Fill(data2);
MessageBox.Show("Project Details Save...");
clear();
refresh();
}
}
From the information you've provided, it seems you are creating a value in two tables based on Contract_Id column and you are checking if the record already exists, you do not insert the records, otherwise you post the records.
Since, I cannot see the relationship between tbl_project and tbl_expense, I assume you are trying to insert Contract_Id as a foreign key in both the tables.
If that is the case, then I would suggest use below version of the code.
public void InsertIfNotExists()
{
if (textID.Text == "" && textProject.Text == "" && textAmount.Text == "")
{
MessageBox.Show("Please Enter Details..!");
}
else
{
using(var connection = new SqlConnection(DbConnectionString)) // Pass DbConnectionString for your SQL server instance
{
var query = #"
IF NOT EXISTS (SELECT * FROM tbl_project WHERE Contract_ID = #Contract_ID)
BEGIN
-- Here we are checking if the row already exists for the variable #Contract_ID
INSERT INTO tbl_project (Contract_ID, Contract_Amount, Contractor, Project_Name, Start_Date, End_Date, Year, Address, Remarks, Status)
VALUES (#Contract_ID, #Contract_Amount, #Contractor, #Project_Name, #Start_Date, #End_Date, #Year, #Address, #Remarks, #Status);
-- We are inserting the values since Contract_ID was not matched in the database.
INSERT INTO tbl_expense (CONTRACT, CONTRACT_ID, CONTRACTOR, PROJECT_STATUS, COVERED_PERIOD, END_PERIOD, PROJECT_AMOUNT)
VALUES (#CONTRACT, #CONTRACT_ID, #CONTRACTOR, #PROJECT_STATUS, #COVERED_PERIOD, #END_PERIOD, #PROJECT_AMOUNT);
-- We are inserting expense based on Contract_ID
END;
"
;
using (var cmd = new SqlCommand(query, connection))
{
cmd.Parameters.AddWithValue("#Contract_ID", textID.Text);
cmd.Parameters.AddWithValue("#Contract_Amount", textAmount.Text);
cmd.Parameters.AddWithValue("#Contractor", textContract.Text);
cmd.Parameters.AddWithValue("#Project_Name", textProject.Text);
cmd.Parameters.AddWithValue("#Start_Date", dateTimePicker1.Value.Date);
cmd.Parameters.AddWithValue("#End_Date", dateTimePicker2.Value.Date);
cmd.Parameters.AddWithValue("#Year", textYear.Text);
cmd.Parameters.AddWithValue("#Address", textAddress.Text);
cmd.Parameters.AddWithValue("#Remarks", textOthers.Text);
cmd.Parameters.AddWithValue("#Status", comboBox5.Text);
cmd.Parameters.AddWithValue("#CONTRACT", textProject.Text);
cmd.Parameters.AddWithValue("#CONTRACTOR", textContract.Text);
cmd.Parameters.AddWithValue("#PROJECT_STATUS", comboBox5.Text);
cmd.Parameters.AddWithValue("#COVERED_PERIOD", dateTimePicker1.Value.Date);
cmd.Parameters.AddWithValue("#END_PERIOD", dateTimePicker2.Value.Date);
cmd.Parameters.AddWithValue("#PROJECT_AMOUNT", textAmount.Text);
connection.Open();
var rA = cmd.ExecuteNonQuery();
connection.Close();
MessageBox.Show(rA > 0 ? "Data Successfully saved!" : "Data already exists!");
}
}
}
}
In the code above, we are formulating the SQL Statement in a way, that you do not have to fetch and compare and then post to the database, saves you from the round trips for a simple operation.
Also, you'll notice, we are using parameterized query, where we are passing the parameters in the SQL statement, as mentioned in the comments by #Always Learning, it is a good thing from guys who try to mess around with your database, this will prevent SQL Injections.
I need to insert 388 datas per minute to local Database.
At first when the table is Empty, I only need 5 second to Insert to database.
But when the table gets larger, the program efficacy slow down to more than one minute when the amount of rows comes to 1,026,558.
And the useage of CPU is 100%. It's unusual.
here is my code:
public static void dataToDB(String[] routeIDArray,String[] levelArray,String[] valueArray,String[] travelTimeArray, int amountOfData)
{
MySqlConnection con = new MySqlConnection(connStr);
MySqlCommand cmd = null;
MySqlDataReader rdr = null;
String sqlCmd, updateSqlCmd = "UPDATE `datetimetable` SET ";
for(int counter = 0; counter < amountOfData; counter++)
{
sqlCmd = "ALTER TABLE `datetimetable` ADD COLUMN IF NOT EXISTS `" + routeIDArray[counter] + "` INT NULL;"
+ "INSERT INTO `roadvalue`.`data` (`level`,`value`,`traveltime`) VALUES ("
+ levelArray[counter] + ","
+ valueArray[counter] + ","
+ travelTimeArray[counter] + ");"
+ "SELECT LAST_INSERT_ID() FROM `data`;";
cmd = new MySqlCommand(sqlCmd, con);
con.Open();
rdr = cmd.ExecuteReader();
rdr.Read();
updateSqlCmd += "`" + routeIDArray[counter] + "` = " + rdr[0] + ",";
rdr.Close();
}
updateSqlCmd = updateSqlCmd.TrimEnd(',');
updateSqlCmd += " WHERE EXISTS (SELECT * WHERE dateTime = '" + dateTime.ToString("yyyy-MM-dd HH:mm:00") + "');";
cmd = new MySqlCommand(updateSqlCmd, con);//update data key to datetimetable
cmd.ExecuteNonQuery();
Console.WriteLine("Done.");
con.Close();
}
public static void checkDateTimeExisted()
{
MySqlConnection con = new MySqlConnection(connStr);
MySqlCommand cmd;
String sqlCmd;
sqlCmd = "INSERT INTO `datetimetable` (`dateTime`) SELECT * FROM (SELECT '" + dateTime.ToString("yyyy-MM-dd HH:mm:00")
+ "') AS tmp WHERE NOT EXISTS(SELECT `dateTime` FROM `datetimetable` WHERE `dateTime` = '" + dateTime.ToString("yyyy-MM-dd HH:mm:00") + "') LIMIT 1; ";
con.Open();
cmd = new MySqlCommand(sqlCmd, con);
cmd.ExecuteNonQuery();
con.Close();
}
And Mysql Engine is InooDB, table "data" has one Auto_Increment Primary key, table "datetimetable" has an Auto_Increment Primary key and a not duplicate datetime as index.
What have I done wrong?
I find the answer, the command "SELECT LAST_INSERT_ID() FROM data;" should add LIMIT 1 or it will get all the ID kill the performance.
Do not use ALTER TABLE in a loop -- Plan ahead and provide all the columns before starting.
Do not use multiple statements in a single string. This has security implications, etc.
Do not use WHERE EXISTS... when (I think) a simple WHERE would work.
If there is UNIQUE(datetime), then the final INSERT can be simply
INSERT IGNORE INTO datetimetable
(datetime)
VALUE
('...');
Do batch inserts unless you need the LAST_INSERT_ID(). LIMIT 1 should not be necessary.
Do not 'Normalize' datetime values; it only slows things down. Just put the datetime as is in the main table.
I created a query to insert into two ms access tables at a time in c#. I got the exception
{System.Data.OleDb.OleDbException: Characters found after end of SQL
statement. at
System.Data.OleDb.OleDbCommand.ExecuteCommandTextErrorHandling(OleDbHResult
hr) at
System.Data.OleDb.OleDbCommand.ExecuteCommandTextForSingleResult(tagDBPARAMS
dbParams, Object& executeResult) at
System.Data.OleDb.OleDbCommand.ExecuteCommandText(Object&
executeResult) at
System.Data.OleDb.OleDbCommand.ExecuteCommand(CommandBehavior
behavior, Object& executeResult) at
System.Data.OleDb.OleDbCommand.ExecuteReaderInternal(CommandBehavior
behavior, String method) at
System.Data.OleDb.OleDbCommand.ExecuteNonQuery() at
CompanyDetails.Model.CompanyDetailsModel.setCompanyDetailsToDB(CompanyDetailsDataList
_cmpDetailsList) in E:\Project\PBAttendence\ModifyPrivileage\CompanyDetails\Model\CompanyDetailsModel.cs:line
62}
my sample code is given below please solve my problem. sorry for my bad English.
int companyID = _cmpDetailsList[0].CompanyID;
string companyName = _cmpDetailsList[0].CompanyName;
string contactID = _cmpDetailsList[0].ContactID;
string companyAddress = _cmpDetailsList[0].CompanyAddress;
if (companyID == -1)
{
OleDbCommand cmd = new OleDbCommand("Insert into CompanyDetails([CompanyName],[CompanyAddress],[ContactID]) values ('" + companyName + "','" + companyAddress + "','" + contactID + "');Insert into UserCompanyDetails([UserID],[CompanyID]) values (" + "Select [UserID] from UserDetails;" + "," + "Select ##identity;" + "); ", conn);
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
else
{
OleDbCommand upcmd = new OleDbCommand("update CompanyDetails set [CompanyName] = '" + companyName + "',[CompanyAddress] = '" + companyAddress + "',[ContactID] = '" + contactID + "' where [CompanyID] = #cmpID;", conn);
conn.Open();
upcmd.Parameters.AddWithValue("#cmpID", companyID);
upcmd.ExecuteNonQuery();
conn.Close();
}
now i split into two insert command but i got the error {System.Data.OleDb.OleDbException: Syntax error. in query expression 'Select [UserID] from UserDetails;
OleDbCommand cmd = new OleDbCommand("Insert into CompanyDetails([CompanyName],[CompanyAddress],[ContactID]) values ('" + companyName + "','" + companyAddress + "','" + contactID + "');", conn);
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
OleDbCommand cmd1 = new OleDbCommand("Insert into UserCompanyDetails([UserID],[CompanyID]) values (" + "Select [UserID] from UserDetails;" + "," + "Select ##identity" + ");", conn);
conn.Open();
cmd1.ExecuteNonQuery();
conn.Close();
The problem is this line of code:
OleDbCommand cmd = new OleDbCommand("Insert into CompanyDetails([CompanyName],[CompanyAddress],[ContactID]) values ('" + companyName + "','" + companyAddress + "','" + contactID + "');Insert into UserCompanyDetails([UserID],[CompanyID]) values (" + "Select [UserID] from UserDetails;" + "," + "Select ##identity;" + "); ", conn);
You have two insert statements in the same OleDbCommand. Try to move this into two different steps:
Insert into CompanyDetails table
Insert into UserCompanyDetails table
Hope this helps you
First of all , it would have been easier with the raw sql command then your code generating the sql.
You might consider making a stored procedure since your command is getting kinda complex
If i'm correct , what you are currently trying to do is :
Insert into table1(x,y,z) values a,b,c;
Insert into table2(x,y) values select * from table3; , ##identity
The second sql command is invalid in both syntax and logic, your ##identity won't be static since you're inserting new records during your command.
My recommendation would be to do something like this :
Insert into table1(x,y,z) values a,b,c;
declare #table1Id int = ##identity
Insert into table2(x,y) select colA, #table1Id from table3;
You cannot have ; in queries in Access. See http://office.microsoft.com/en-us/access-help/HV080760224.aspx You will have to do the two inserts separately as suggested by #juanreyesv
You will have to do 3 queries,
Do the insert using your sql: "Insert into CompanyDetails([CompanyName],[CompanyAddress],[ContactID]) values ('" + companyName + "','" + companyAddress + "','" + contactID + "')
Get the ##identity using
Select ##identity and store it in a variable say idnt
Use the identity value obtained in 2. to do the third insert:
"Insert into UserCompanyDetails([UserID],[CompanyID])
Select UserID, " + idnt.ToString() + " from UserDetails"
Refer to http://msdn.microsoft.com/en-us/library/ks9f57t0%28VS.71%29.aspx
String strSql = "insert into BaseData (Item," + dataGridView1.Columns[3].Name + "," + dataGridView1.Columns[4].Name + ") values ('" + row.Cells[0].Value + "','" + row.Cells[3].Value + "','" + row.Cells[4].Value + "')";
objCmd = new OleDbCommand(strSql, lConn);
objCmd.ExecuteNonQuery();
strSql = "select id from BaseData where Item = '" + row.Cells[0].Value + "' and " + dataGridView1.Columns[1].Name + " = '" + row.Cells[3].Value + "' And " + dataGridView1.Columns[2].Name + " = '" + row.Cells[4].Value + "'";
OleDbCommand command = new OleDbCommand(strSql, lConn);
OleDbDataReader reader = command.ExecuteReader();
String id = "";
while (reader.Read())
{
id = reader.GetString(0);
}
reader.Close();
strSql = "insert into tranjaction (Base_id,quentity,price,other) values ('" + id + "' , ' " + row.Cells[2].Value + "','" + row.Cells[1].Value + "')";
objCmd = new OleDbCommand(strSql, lConn);
objCmd.ExecuteNonQuery();
When I run this, Microsoft Visual Studio Error occur on Line 10. (ExecuteReader)
The Error is here.
An unhandled exception of type 'System.Data.OleDb.OleDbException'
occurred in System.Data.dll
Additional information: No value given for one or more required
parameters.
How could I fix this error?.
Either your field names are wrong (quentity?) or it's because you have unbalanced fields to parameters. You are inserting into 4 fields, but you are only supplying 3 values. Use parameters instead, it would make your life easier.
Try changing it to this:
strSql = "insert into tranjaction (Base_id,quentity,price,other) values (#id , #quentity, #price, #other)";
using (OleDbCommand cmd = new OleDbCommand(sqlSql, IConn)) {
cmd.Parameters.AddWithValue("#id", id);
cmd.Parameters.AddWithValue("#quentity", row.Cells[2].Value);
cmd.Parameters.AddWithValue("#price", row.Cells[1].Value);
cmd.Parameters.AddWithValue("#other", other); // <- missing
cmd.ExecuteNonQuery();
}
When I've received this error in the past it has always been because of a simple typo. Like the others have mentioned it looks like you spelled "quantity" wrong which could be part of the problem.
In this line
strSql = "insert into tranjaction (Base_id,quentity,price,other) values ('" + id + "' , ' " + row.Cells[2].Value + "','" + row.Cells[1].Value + "')";
you are inserting 4 values (Base_id,quentity,price,other), but you are only inserting 3 values (id, row.Cells[2].Value, row.Cells[1].Value). Giving a value for other should fix the problem.
Another thing that would cause this error, which is probably your situation, is if you've spelled one of the column names incorrectly. And since you are using column names from your datagridview, and some of your written column names seem mis-spelled, you should double check the spelling in your query strings.
how to execute SQL with if condition in c#?
This is my query and went i execute this query i get an error saying "Invalid SQL statement; expected 'DELETE', 'INSERT', 'PROCEDURE', 'SELECT', or 'UPDATE'."
I m using MS ACCESS as back end
mycon.ConnectionString = ConnString;
mycon.Open();
string mySelectQuery = "IF (EXISTS (SELECT * FROM Employee AS t1 WHERE t1.ssn ='"+textBox4.Text+"' "+
"))begin UPDATE Employee SET "+
"fname ='"+textBox1.Text+"' ,"+
"minit ='"+textBox2.Text+"' ," +
"lname ='" + textBox3.Text+"', " +
"ssn ='" +textBox4.Text+"', " +
"bdate ='" +textBox5.Text+"', " +
"address ='" +textBox6.Text+"', " +
"sex ='" +textBox7.Text+ "', " +
"salary ='" +textBox8.Text+"', " +
"superssn ='" +textBox9.Text+"', " +
"dno ='" +comboBox2.Text+"'" +
" WHERE ssn = '"+textBox4.Text+"' "+
"end "+
"else "+
" begin "+
" INSERT INTO employee values ('"+textBox1.Text+"','"+textBox2.Text+"','"+textBox3.Text+"','"+textBox4.Text+"','"+textBox5.Text+"','"+textBox6.Text+"','"+textBox7.Text+"','"+textBox8.Text+"','"+textBox9.Text+"','"+comboBox2.Text+"')"+
" end";
OleDbCommand myCommand = new OleDbCommand(mySelectQuery, mycon);
int Success= myCommand.ExecuteNonQuery();
MS Access doesn't support the IF statement. Nor else or begin. You'll have to do this in your C# code, such as performing your "SELECT * FROM Employee AS t1 WHERE t1.ssn ='"+textBox4.Text + "'"; query first and then performing the next one if there are results.
Also, you should either use a parameterized queries or escape the values of you text boxes.
Seems like what you want to happen is UPDATE a record if it Exists in database, else INSERT a record.
You can't do this in one query, so prepare a query for a look-up in database if the record exists, then use the output (isExists or not) to UPDATE or INSERT