Conditional SQL statement - switching between insert/update query [duplicate] - c#

This question already has answers here:
Upserting in MS-access
(6 answers)
Closed 9 years ago.
Is there a way to insert if/else clause into the following line here:
command.CommandText = "UPDATE Table1 SET ID=value1,Team=value2 WHERE ID=value3";
In a case where ID=value3 (in other words the row already exists) can be found then an update query takes place but where it cannot be found I want an insert query to take place:
command.CommandText = "INSERT INTO Table1 (ID,Team) VALUES (value1,value2)";
to take place... how can I do that?
private void button1_Click(object sender, EventArgs e)
{
// save to access database when user clicks on the save button
using (OleDbConnection conn = new OleDbConnection())
{
//the file path of mdb
string filepath = #"C:\Users\sy\Visual Studio 2008\Projects\demo\demo\CE_Database.mdb";
conn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;data source=" + filepath + ";";
OleDbCommand command = new OleDbCommand();
command.Connection = conn;
//your update satemenet
command.CommandText = "UPDATE Table1 SET ID=value1,Team=value2 WHERE ID=value3";
conn.Open();
//update to ms access
command.ExecuteNonQuery();
conn.Close();
}
}

Since command.ExecuteNonQuery(); will return the number of rows affected, you can check what this returns from the update command, if the record does not exist the method will return 0, then you can then progress to the insert method:
private string filepath = #"C:\Users\sy\Visual Studio 2008\Projects\demo\demo\CE_Database.mdb";
private string connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;data source=" + filepath + ";";
private void button1_Click(object sender, EventArgs e)
{
if (this.Update() == 0)
{
this.Insert();
}
}
private int Update()
{
using (OleDbConnection conn = new OleDbConnection(connectionString))
using (OleDbCommand command = new OleDbCommand("UPDATE Table1 SET ID=value1,Team=value2 WHERE ID=value3", conn);
{
conn.Open();
return command.ExecuteNonQuery();
}
}
private int Insert()
{
using (OleDbConnection conn = new OleDbConnection(connectionString))
using (OleDbCommand command = new OleDbCommand("INSERT INTO Table1 (ID,Team) VALUES (value1,value2)", conn);
{
conn.Open();
return command.ExecuteNonQuery();
}
}
To clear up comments on the answer, the OleDbConnection.Dispose() method looks like this:
protected override void Dispose(bool disposing)
{
if (disposing)
{
this._userConnectionOptions = null;
this._poolGroup = null;
this.Close();
}
this.DisposeMe(disposing);
base.Dispose(disposing);
}
So the connection will be closed by the Dispose method, so there is no need to explicitly call Close() when your connection is in a using block

Sounds like you're after the MERGE statement... which doesn't exist in the JET version of SQL. This'll work for most things though:
UPDATE Table1 RIGHT JOIN Table2
ON Table1.[KeyField] = Table2.[KeyField]
SET Table1.[KeyField] = Table2.[KeyField],
Table1.[OtherField] = Table2.[OtherField]
If it is in Table2, it will be inserted into Table1, overwriting the value (updating), if it's already in Table1.

It's simple. Check for the existence of ID = 3 through a SELECT COUNT(*) query before running INSERT or UPDATE.

You could do the UPDATE query first with ExecuteNonQuery(), which returns the number of affected rows.
If affected rows are 0, then you'll run your INSERT query.
//the file path of mdb
string filepath = #"C:\Users\sy\Visual Studio 2008\Projects\demo\demo\CE_Database.mdb";
conn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;data source=" + filepath + ";";
OleDbCommand command = new OleDbCommand();
command.Connection = conn;
//your update satemenet
command.CommandText = "UPDATE Table1 SET ID=value1,Team=value2 WHERE ID=value3;";
conn.Open();
//update to ms access
int affectedRows = command.ExecuteNonQuery(); // returns 1 if the row exist, 0 if it does not.
if (affectedRows == 0)
{
command.CommandText = "INSERT INTO Table1 (ID,Team) VALUES (value1,value2)";
command.ExecuteNonQuery(); // perform insert
}
conn.Close()
EDIT: As Gord Thompson pointed out, the original solution did not work. ExecuteScalar() with "UPDATE .....; SELECT ##ROWCOUNT". Changed this to use ExecuteNonQuery, and get the number of affected rows from that method.
Old solution using ##ROWCOUNT:
command.CommandText = "UPDATE Table1 SET ID=value1,Team=value2 WHERE ID=value3; SELECT ##ROWCOUNT;";
conn.Open();
//update to ms access
int affectedRows = (int)command.ExecuteScalar(); // returns 1 if the row exist, 0 if it does not.
if (affectedRows == 0)
{
command.CommandText = "INSERT INTO Table1 (ID,Team) VALUES (value1,value2)";
command.ExecuteNonQuery(); // perform insert
}

Use ##ROWCOUNT
command.CommandText = "UPDATE Table1 SET ID=value1,Team=value2 WHERE ID=value3 IF ##ROWCOUNT = 0 INSERT INTO Table1 (ID,Team) VALUES (value1,value2)"
Edit: As Gord said this won't work, I was too fast, didn't notice it's Access.
This is a similar question and solution.

Related

Second query failed to update because first query still in insert progress

private void btnSave_Click(object sender, EventArgs e)
{
using (OleDbConnection con = new OleDbConnection(cs))
{
con.Open();
cmd = new OleDbCommand(“INSERT INTO table1 ([name], [gender], [age]) VALUES ('Jeff', 'Male', 51), con);
cmd.ExecuteNonQuery();
//System.Threading.Thread.Sleep(1000); // it's working if i add a delay here
//int success = cmd.ExecuteNonQuery(); // also working if check number of query affected
//if (success > 0)
//{
// updateLastModified();
//}
updateLastModified();
}
}
public void updateLastModified()
{
using (OleDbConnection con = new OleDbConnection(cs))
{
con.Open();
cmd = new OleDbCommand("UPDATE TABLE1 SET LastModifiedTime='" + DateTime.Now.ToString() + "' WHERE name='Jeff'", con);
cmd.ExecuteNonQuery();
// this was not updated because "Jeff" cannot be found in table1 (first insert query still running)
}
}
My problem was second query not updated because first query still running.
Any better solution other than "adding a delay" or "check first query was successful" before perform second query?
This is just an example scenario, I'm not going to do in one query.
Update:
Suggestion from #a.rlx was using OleDbTransaction.Commit method. Can i do by this way without using try catch?
using (OleDbConnection con = new OleDbConnection(cs))
{
OleDbTransaction transaction = null;
con.Open();
transaction = con.BeginTransaction();
cmd = new OleDbCommand(“INSERT INTO table1 ([name], [gender], [age]) VALUES ('Jeff', 'Male', 51), con, transaction);
cmd.ExecuteNonQuery();
transaction.Commit();
updateLastModified();
}
Have you tried to start a transaction, run both SQL statements, and then commit the transaction?
https://dev.mysql.com/doc/dev/connector-net/6.10/html/M_MySql_Data_MySqlClient_MySqlConnection_BeginTransaction.htm

How can I retrieve the ID of the inserted row using ExecuteScalar function and the SCOPE_IDENTITY() function

I need to be able to get the ID (so I can then pass it through an Add News query) of the inserted row for my image upload table, so I can INNER JOIN a news item to it.
According to my research I need to use ExecuteScalar function and the SCOPE_IDENTITY() function.
Any suggestions on how I can achieve this will be greatly appreciated.
protected void btnUpload_Click(object sender, EventArgs e)
{
if (FileUpload1.PostedFile != null)
{
SqlConnection con = new SqlConnection(strConnString);
string strQuery = "insert into tblFiles (FileName, FilePath)
values(#FileName, #FilePath)"
SqlCommand cmd = new SqlCommand(strQuery);
cmd.Parameters.AddWithValue("#FileName", FileName);
cmd.Parameters.AddWithValue("#FilePath", "/images/admin/news/" + FileName);
cmd.CommandType = CommandType.Text;
cmd.Connection = con;
try {
con.Open();
cmd.ExecuteNonQuery();
}
finally {
con.Close();
con.Dispose();
}
}
}
Once I have the ID I can do another SQL query to insert the news item, with the correct pic ID.
First things first you need to use Store Procedures instead of just writing your SQL statements inside your application.
Second what you want is to run SCOPE_IDENTITY as part of your insert statement like
INSERT INTO tblFiles (FileName, FilePath)
VALUE(#FileName, #FilePath);
SELECT SCOPE_IDENTITY()
And then change the execution statement in .NET to ExecuteScalar
var result = cmd.ExecuteScalar();

C# checking if order number already exists

I've been looking into How to check user id already exists to see how to do this.
I am trying to get this working in my code, however it's not working. I don't get errors or something, but it just write data in database even if order number already exists.
The function:
private void createorderButton_Click(object sender, EventArgs e)
{
SqlConnection myConnection = dbHelper.initiallizeDB();
String query = "INSERT INTO testtabel (knaam, korder) VALUES ('" + knaamTextBox.Text + "','" + kordernrTextBox.Text + "')";
SqlCommand sqlCommand = new SqlCommand(query, myConnection);
SqlCommand cmd = new SqlCommand("select * from testtabel where korder = #korder", myConnection);
SqlParameter param = new SqlParameter();
param.ParameterName = "#korder";
param.Value = kordernrTextBox.Text;
cmd.Parameters.Add(param);
//sqlCommand.Connection.Open();
SqlDataReader reader = sqlCommand.ExecuteReader();
if (reader.HasRows)
{
MessageBox.Show("Order already exist");
}
else
{
reader.Close();
}
// opens execute non query
int rows_inserted = sqlCommand.ExecuteNonQuery();
if (rows_inserted > 0)
{
label2.Text = "Order has been created";
}
else
{
Console.Write("Oops! Something wrong!");
}
}
Sorry for this kinda well known and duplicated question, but for some reason I can't get it working.
You called the wrong command, change
SqlDataReader reader = sqlCommand.ExecuteReader();
to
SqlDataReader reader = cmd.ExecuteReader();
The problem is here:
SqlDataReader reader = sqlCommand.ExecuteReader();
You should execute the other command first
SqlCommand cmd = new SqlCommand("select * from testtabel where korder = #korder", myConnection);
The latter command, when will be executed will tell you if there is any record in the testtabel table. If there is, then you should show the message:
Order already exist
Otherwise, you will execute your first command, that will insert the rows.
By the way, please try to avoid string concatenation, when you write sql queries. It is one of the most well known security holes. You code is open to SQL injections. You could use parameterized queries:
String query = "INSERT INTO testtabel (knaam, korder) VALUES (#knaam, #korder)";
SqlCommand sqlCommand = new SqlCommand(query, myConnection);
sqlCommand.Parameters.Add(new SqlParamete("#knaam",knaamTextBox.Text));
sqlCommand.Parameters.Add(new SqlParamete("#korder",kordernrTextBox.Text));
While your code is full of problems (magic pushbutton, SQL injections, absence of usings), there is main one. The approach you want to implement will fail on concurrent inserts, and must not be used.
Imagine, that two users run this code against the same database, using the same korder value:
1st executes SELECT - record with the given value doesn't exist;
2nd executes SELECT - record with the given value doesn't exist;
1st executes INSERT - record with the given value does exist;
2nd executes INSERT - ooops... we have a duplicate;
To avoid duplicates you must use unique indexes in database. Do not rely on your code.
You check HasRows for INSERT INTO testtabel bla...bla..bla.. not for `elect * from testtabel where korder'
Maybe you can use this (it comes from my head and not compiled, please adjust it with your own case)
private void createorderButton_Click(object sender, EventArgs e)
{
SqlConnection myConnection = dbHelper.initiallizeDB();
String query = "INSERT INTO testtabel (knaam, korder) VALUES ('" + knaamTextBox.Text + "','" + kordernrTextBox.Text + "')";
SqlCommand sqlCommand = new SqlCommand(query, myConnection);
SqlCommand cmd = new SqlCommand("select * from testtabel where korder = #korder", myConnection);
SqlParameter param = new SqlParameter();
param.ParameterName = "#korder";
param.Value = kordernrTextBox.Text;
//sqlCommand.Connection.Open();
SqlDataReader cmdReader = sqlCommand.ExecuteReader();
if (cmdReader.HasRows)
{
MessageBox.Show("Order already exist");
}
else
{
cmdReader.Close();
}
SqlDataReader reader = sqlCommand.ExecuteReader();
// opens execute non query
int rows_inserted = sqlCommand.ExecuteNonQuery();
if (rows_inserted > 0)
{
label2.Text = "Order has been created";
}
else
{
Console.Write("Oops! Something wrong!");
}
}

Display number of records in a table

I'm trying to display numbers of records (in table) using C# Windows form . Bud It display "1" as output for every time . Here is the code.
private void button1_Click(object sender, EventArgs e)
{
string constr = #"Data Source=(LocalDB)\v11.0;AttachDbFilename=C:\Users\Visual Studio/database.mdf;Integrated Security=True";
SqlConnection con = new SqlConnection(constr);
con.Open();
string query= "select Count(*) from Student where Name like '%b%' ";
SqlCommand cmd = new SqlCommand(query1, con);
SqlDataReader dr = cmd.ExecuteReader();
int count = 1;
while (dr.Read())
{count++;}
label1.Text ="Following records : "+count+" ";
}
selecting count(*) returns one record with the value of the column holding the number of rows in the table. You don't need to count the number of rows in the result, you just need to get it from the first (and only) row:
int count = 0;
if (dr.Read()) {
count = dr.GetInt32(0);
} else {
// something went horribly wrong. Throw an exception perhaps?
}
If you need to count all of your records, then you need to remove LIKE filter from the query.
You do not have to use SqlDataReader - the ExecuteScalar is enough.
For the start, your code should be:
private void button1_Click(object sender, EventArgs e)
{
string constr = #"Data Source=(LocalDB)\v11.0;AttachDbFilename=C:\Users\Visual Studio/database.mdf;Integrated Security=True";
SqlConnection con = new SqlConnection(constr);
con.Open();
string query= "select Count(*) from Student";
SqlCommand cmd = new SqlCommand(query1, con);
int count = (int)cmd.ExecuteScalar();
label1.Text ="Following records : "+count+" ";
}
Also, consider learning about using statement which enforces good practice for releasing and disposing resources.
Very important thing when you work with the database connections, transactions and commands.
SqlCommand with using statement
i think you should use rownum function it will display the number for each record for more info check this link http://docs.oracle.com/cd/B12037_01/server.101/b10759/pseudocolumns008.htm

If not exists then insert else show message "Already exists"

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
namespace Barcode
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string strconn = #"Data Source=ASHWINI-LAPY\SQLEXPRESS;Initial Catalog=complete;Integrated Security=True;Pooling=False";
SqlDataReader reader = null;
SqlConnection conn = null;
conn = new SqlConnection(strconn);
conn.Open();
DateTime Dt_Time = DateTime.Now;
string Barcode = textBox1.Text;
SqlCommand cmd = new SqlCommand("select Barcode from table3 where #Barcode='" + textBox1.Text + "'", conn);
cmd.Parameters.AddWithValue("#Barcode", textBox1.Text);
reader = cmd.ExecuteReader();
if (reader != null && reader.HasRows)
{
//email exists in db do something
MessageBox.Show("Barcode Already Exists!!");
}
else
{
string strquery = string.Format("insert into table3 values('{0}','{1}')", Barcode, Dt_Time);
cmd = new SqlCommand(strquery, conn);
int count = (int)cmd.ExecuteNonQuery();
MessageBox.Show("Barcode:" + Barcode +
"\nTime" + Dt_Time);
}
I am new to C# coding so I tried to do it like what I mentioned below in code, so please somebody help me.
I want to insert a barcode manually and when I press button the SQL Server database has to be checked whether that barcode exists. If not, it has to insert that barcode into the database, but if it already exists, it has to give a message that barcode already exists!
Along with inserting barcode I am also inserting system date and time also in database.
EDIT
C# code that you can write in your button click event
using (System.Data.SqlClient.SqlConnection cn =
new System.Data.SqlClient.SqlConnection(#"Data Source=ASHWINI-LAPY\SQLEXPRESS;Initial Catalog=complete;Integrated Security=True;Pooling=False"+
"Integrated Security=True"))
{
using (System.Data.SqlClient.SqlCommand cmd= new System.Data.SqlClient.SqlCommand("IsBarcodeCheckAndInsert", cn))
{
cmd.CommandType=CommandType.StoredProcedure ;
SqlParameter parm= new SqlParameter("#BarCode", cn",SqlDbType.VarChar) ;
parm.Value="ALFKI";
parm.Size=25;
parm.Direction =ParameterDirection.Input ;
cmd.Parameters.Add(parm);
SqlParameter parm2=new SqlParameter("#IsExists",SqlDbType.Int);
parm2.Direction=ParameterDirection.Output;
cmd.Parameters.Add(parm2);
cn.Open();
cmd.ExecuteNonQuery();
cn.Close();
int IsExists = Convert.ToInt32(cmd.Parameters["#IsExists"].Value.ToString());
if(IsExists ==0)
MessageBox.Show("Barcode Already Exists !!");
else if(IsExists ==1)
MessageBox.Show("Barcode not Exists And Inserted In DataBase!!");
}
}
SQL Procdure
CREATE PROCEDURE [dbo].[IsBarcodeCheckAndInsert]
(
#BarCode AS VARCHAR(25),
#IsExists AS INT out )
AS
BEGIN
IF EXISTS (SELECT * FROM table3 WHERE BarCode = #BarCode )
BEGIN
set #IsExists =1
END
ELSE
BEGIN
Insert into table3 values(#BarCode ,getDate())
set #IsExists =0
END
END
Whats wrong with the code I check your code code is fine ..if it's not working at you end what error you are getting.
Just on recommandation make use of SQLParameter in your second queryi.e in insert query also to avoid SQLInjection attack for more detail check here : How does SQLParameter prevent SQL Injection?
Check out these lines of code:
string Barcode = textBox1.Text;
SqlCommand cmd = new SqlCommand("select Barcode from table3 where #Barcode='" + textBox1.Text + "'", conn);
cmd.Parameters.AddWithValue("#Barcode", textBox1.Text);
If textBox1.Text is equal to "example", the resulting SQL query would be
Select Barcode from table3 where 'example'='example'
You might want to change the SqlCommand statement to:
SqlCommand cmd = new SqlCommand("select Barcode from table3 where Barcode=#Barcode", conn);
You can do something like this:
SqlCommand cmd = new SqlCommand("select Barcode from table3 where Barcode=#Barcode", conn);
cmd.Parameters.AddWithValue("#Barcode", textBox1.Text);
Regards
You mixed up your sql parameters syntax, this:
SqlCommand cmd = new SqlCommand("select Barcode from table3 where #Barcode='" + textBox1.Text + "'", conn);
cmd.Parameters.AddWithValue("#Barcode", textBox1.Text);
Should be changed to be like this:
SqlCommand cmd = new SqlCommand("select Barcode from table3 where Barcode = #Barcode", conn);
cmd.Parameters.AddWithValue("#Barcode", textBox1.Text);
Basically you switched the column name with the parameter name in the query.
UPDATE
As for the "There is already an open DataReader..." exception, adjust the code with using blocks (in a "best practice" approach), like this:
private void button1_Click(object sender, EventArgs e)
{
string strconn = "<connection string";
using (SqlConnection conn = new SqlConnection(strconn))
{
bool readerHasRows = false; // <-- Initialize bool here for later use
DateTime Dt_Time = DateTime.Now;
string Barcode = textBox1.Text;
string commandQuery = "SELECT Barcode FROM table3 WHERE Barcode = #Barcode";
using(SqlCommand cmd = new SqlCommand(commandQuery, conn))
{
cmd.Parameters.AddWithValue("#Barcode", textBox1.Text);
using(SqlDataReader reader = cmd.ExecuteReader())
{
// bool initialized above is set here
readerHasRows = (reader != null && reader.HasRows);
}
}
if (readerHasRows)
{
//email exists in db do something
MessageBox.Show("Barcode Already Exists!!");
}
else
{
//Same as above
string strquery = "INSERT INTO table3 VALUES (#Barcode, #DtTime)"; // '{0}','{1}')", Barcode, Dt_Time);
using (SqlCommand cmd = new SqlCommand(strquery, conn))
{
cmd.Parameters.AddWithValue("Barcode", Barcode);
cmd.Parameters.AddWithValue("DtTime", Dt_Time);
int count = cmd.ExecuteNonQuery(); // this already the number of affected rows by itself
// NOTE: '\n' doesn't really work to output a line break.
// Environment.NewLine should be used.
MessageBox.Show("Barcode:" + Barcode + Environment.NewLine + "Time" + Dt_Time);
}
// code probably goes on ...
} // end of using(SqlConnection...
} // end of method
Should at least lead you on the right track.
You can do this in one sql query with the Merge-command.
In plain SQL it will look like:
merge table3 WITH(HOLDLOCK) as target
using (SELECT #Barcode, #DtTime)
as source (Barcode, DtTime)
on target.Barcode = #Barcode
when not matched then
insert ( Barcode, DtTime)
values ( #Barcode, #DtTime);

Categories

Resources