I have tried to give multiple insert or update in single query like
OleDbCommand command = new OleDbCommand("INSERT INTO Employee (Id,
Name, Address, Salary) VALUES (2001, 'name1', 'address1',
100000);UPDATE Employee SET Salary = 2000000 WHERE Id = 2001;");
This executes successfully.
But I don't want multiple sql queries in single execution. Is there anything like any property or something like that in C# which can be used to restrict to only one query.
I want to restrict it to single sql query in single execution.
Thanks.
Try something like this
Create a stringbuilder of values
StringBuilder sb = new StringBuilder();
string sep = "";
for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)
{
sb.AppendFormat("value1","value2" etc);
}
string insertthis = sb.ToString();
Then insert to sql
using (OleDbCommand cmd = new OleDbCommand("INSERT INTO Employee (ItemName) VALUES (#ins)", con))
{
cmd.Parameters.AddWithValue("#ins", insertthis );
cmd.ExecuteNonQuery();
}
MessageBox.Show("Data added");
Update also works like same as insert
Ref
Related
I want to select several values from database (ODBC datasource). The table is this simple:
| name | value |
+------+-------+
| abcd | 12345 |
Say I want to select values where name is name1, name2 and name3:
SELECT name, value FROM my_table WHERE name="name1" OR name="name2" OR name="name3"
Now I could generate this command:
public string MakeCommand(List<string> names) {
string command = "SELECT name, value FROM my_table WHERE ";
bool first = true;
foreach(string name in names) {
if(first)
first = false;
else
command+=" OR ";
command+="name=\""+name+"\"";
}
}
I hope it's not necessary to emphasize that this would be very bad way to access the database.
So how can I make this a parametrized ODBC command, as described here?
Well, the simplest solution is probably to concatenate a parameter to the sql for each value in your list, and then add this value as a parameter to the OdbcCommand.
using(var command = new OdbcCommand())
{
string sql = "SELECT name, value FROM my_table WHERE name IN(";
for(int i=0; i < names.Count; i++) {
sql = $"{sql} #{i},";
command.Parameters.Add($"#{i}", OdbcType.VarChar).Value = names[i];
}
command.CommandText = sql.TrimEnd(",") +");";
command.Connection = con;
// fill a data set or execute a data reader here....
}
There is no elegant solution to this problem. You can use the IN clause but, still you need to build the parameters one by one. So instead of returning a string you can return the OdbcCommand prepared with all the parameters required by your list of names. Just need to add the connection and execute (or pass also the connection and prepare everything here)
public OdbcCommand MakeCommand(List<string> names, OdbcConnection con) {
List<OdbcParameter> parameters = new List<OdbcParameter>();
List<string> placeholders = new List<string>();
foreach(string name in names) {
OdbcParameter p = new OdbcParameter("?", OdbcType.NVarChar);
p.Value = name;
parameters.Add(p);
placeholders.Add("?")
}
string command = "SELECT name, value FROM my_table WHERE name IN(";
command = command + string.Join(",", placeholders.ToArray()) + ")";
OdbcCommand cmd = new OdbcCommand();
cmd.CommandText = command;
cmd.Connection = con;
cmd.Parameters.AddRange(parameters.ToArray());
return cmd;
}
If you still have problems, then it could be something linked to the parameters DataType. NVarChar, VarChar, Text, String. Some db could react differently to this type. What database are you testing this code against?
I have a C# application which retrieves the required information and stores it in a array, I am using Finisar sqlite to create my database entry.
Can anybody guide me as to how I can write retrieved array values to the sqlite database. Any help will be extremely thankful.
Here is what worked for me. In my case, I had a global array and inserted it into sqlite db.
SQLiteConnection con = new SQLiteConnection(/*Your Connection String*/);
string AddFormationTop = "INSERT INTO Formation (WellID, Param1, Param2, Param3)
VALUES ((SELECT WellID FROM Wells WHERE WellName = #WellName), #Param1, #Param2, #Param3)";
SQLiteCommand cmd = new SQLiteCommand(AddFormationTop, con);
string pParam1;
double pParam2;
double pParam3;
con.Open();
// of course, your "for" case might be different.
for (int i = 1; i < GlobalVar.Formation.Length - 1; i++)
{
pParam1 = GlobalVar.Param1[i];
pParam2 = Convert.ToDouble(GlobalVar.Param2[i]);
pParam3 = Convert.ToDouble(GlobalVar.Param3[i]);
cmd.Parameters.AddWithValue("#WellName", Properties.Settings.Default.ActiveWell);
cmd.Parameters.AddWithValue("#Param1", pParam1);
cmd.Parameters.AddWithValue("#Param2", pParam2);
cmd.Parameters.AddWithValue("#Param3", pParam3);
cmd.ExecuteNonQuery();
}
con.Close();
I searched on the net something but nothing really helped me. I want to update, with a list of article, a database, but the way that I've found is really slow.
This is my code:
List<Article> costs = GetIdCosts(); //here there are 70.000 articles
conn = new OleDbConnection(string.Format(MDB_CONNECTION_STRING, PATH, PSW));
conn.Open();
transaction = conn.BeginTransaction();
using (var cmd = conn.CreateCommand())
{
cmd.Transaction = transaction;
cmd.CommandText = "UPDATE TABLE_RO SET TABLE_RO.COST = ? WHERE TABLE_RO.ID = ?;";
for (int i = 0; i < costs.Count; i++)
{
double cost = costs[i].Cost;
int id = costs[i].Id;
cmd.Parameters.AddWithValue("data", cost);
cmd.Parameters.AddWithValue("id", id);
if (cmd.ExecuteNonQuery() != 1) throw new Exception();
}
}
transaction.Commit();
But this way take a lot of minutes something like 10 minutes or more. There are another way to speed up this updating ? Thanks.
Try modifying your code to this:
List<Article> costs = GetIdCosts(); //here there are 70.000 articles
// Setup and open the database connection
conn = new OleDbConnection(string.Format(MDB_CONNECTION_STRING, PATH, PSW));
conn.Open();
// Setup a command
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = conn;
cmd.CommandText = "UPDATE TABLE_RO SET TABLE_RO.COST = ? WHERE TABLE_RO.ID = ?;";
// Setup the paramaters and prepare the command to be executed
cmd.Parameters.Add("?", OleDbType.Currency, 255);
cmd.Parameters.Add("?", OleDbType.Integer, 8); // Assuming you ID is never longer than 8 digits
cmd.Prepare();
OleDbTransaction transaction = conn.BeginTransaction();
cmd.Transaction = transaction;
// Start the loop
for (int i = 0; i < costs.Count; i++)
{
cmd.Parameters[0].Value = costs[i].Cost;
cmd.Parameters[1].Value = costs[i].Id;
try
{
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
// handle any exception here
}
}
transaction.Commit();
conn.Close();
The cmd.Prepare method will speed things up since it creates a compiled version of the command on the data source.
Small change option:
Using StringBuilder and string.Format construct one big command text.
var sb = new StringBuilder();
for(....){
sb.AppendLine(string.Format("UPDATE TABLE_RO SET TABLE_RO.COST = '{0}' WHERE TABLE_RO.ID = '{1}';",cost, id));
}
Even faster option:
As in first example construct a sql but this time make it look (in result) like:
-- declaring table variable
declare table #data (id int primary key, cost decimal(10,8))
-- insert union selected variables into the table
insert into #data
select 1121 as id, 10.23 as cost
union select 1122 as id, 58.43 as cost
union select ...
-- update TABLE_RO using update join syntax where inner join data
-- and copy value from column in #data to column in TABLE_RO
update dest
set dest.cost = source.cost
from TABLE_RO dest
inner join #data source on dest.id = source.id
This is the fastest you can get without using bulk inserts.
Performing mass-updates with Ado.net and OleDb is painfully slow. If possible, you could consider performing the update via DAO. Just add the reference to the DAO-Library (COM-Object) and use something like the following code (caution -> untested):
// Import Reference to "Microsoft DAO 3.6 Object Library" (COM)
string TargetDBPath = "insert Path to .mdb file here";
DAO.DBEngine dbEngine = new DAO.DBEngine();
DAO.Database daodb = dbEngine.OpenDatabase(TargetDBPath, false, false, "MS Access;pwd="+"insert your db password here (if you have any)");
DAO.Recordset rs = daodb.OpenRecordset("insert target Table name here", DAO.RecordsetTypeEnum.dbOpenDynaset);
if (rs.RecordCount > 0)
{
rs.MoveFirst();
while (!rs.EOF)
{
// Load id of row
int rowid = rs.Fields["Id"].Value;
// Iterate List to find entry with matching ID
for (int i = 0; i < costs.Count; i++)
{
double cost = costs[i].Cost;
int id = costs[i].Id;
if (rowid == id)
{
// Save changed values
rs.Edit();
rs.Fields["Id"].Value = cost;
rs.Update();
}
}
rs.MoveNext();
}
}
rs.Close();
Note the fact that we are doing a full table scan here. But, unless the total number of records in the table is many orders of magnitude bigger than the number of updated records, it should still outperform the Ado.net approach significantly...
I'm gathering a list of users and their information that I would like to store in a database table. I have this database set up in Microsoft SQL Server Management Studio. The primary key of the database is set to auto-incrementing. I need the loop to end when there are no more users in the list. I have two valid users in the test account however what I currently have only inserts a single user. Would I be better off to use a sqlDataAdapter?
List<User> result = ims.ListUsers(req).ListUsersResult.Users;
SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["default"].ConnectionString);
for (int i = 1; i < result.Count(); i++)
{
foreach (User user in result.Where(x => x.UserName.Contains('#')))
{
string sql = #"INSERT INTO UserInfo (UserID, UserName) VALUES (#UserID, #UserName)";
using (SqlCommand command = new SqlCommand(sql, connection))
{
command.Parameters.AddWithValue("#UserID", i);
command.Parameters.AddWithValue("#UserName", user.UserName);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
}
}
}
I don't understand why you need the outer for-loop to create the ID since you should not set the primary key column manually. It will increment automatically. You should also always close a connection when you're finished
Here is the complete code:
string sql = #"INSERT INTO UserInfo (UserName) VALUES (#UserName)";
using(var con = new SqlConnection(ConfigurationManager.ConnectionStrings["default"].ConnectionString))
using(var cmd = new SqlCommand(sql, con))
{
con.Open();
foreach(var user in result.Where(x => x.UserName.Contains('#')))
{
// you don't need to set the UserID when you've set made it an Identity column
cmd.Parameters.AddWithValue("#UserName", user.UserName);
cmd.ExecuteNonQuery();
}
}
I think you need to replace:
for (int i = 1; i < result.Count(); i++)
With:
for (int i = 0; i < result.Count(); i++)
Your problem is that you have 2 loops. You need to remove the first for loop and instead increment a int variable each time you execute through your foreach()
You are adding multiple users with the same UserID
int userID = 1
foreach (User user in result.Where(x => x.UserName.Contains('#')))
{
// your code
userID++;
}
You do not need to update auto-incrementing field, it will count automatically by SQL server. Try this code:
List<User> result = ims.ListUsers(req).ListUsersResult.Users;
SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["default"].ConnectionString);
foreach (User user in result.Where(x => x.UserName.Contains('#')))
{
string sql = #"INSERT INTO UserInfo (UserName) VALUES (#UserName)";
using (SqlCommand command = new SqlCommand(sql, connection))
{
command.Parameters.AddWithValue("#UserName", user.UserName);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
}
}
This program was already written and I need to add to it an update SQL statement to update another table based on #IN. After declaring the SQL command how do I get it to excute, can I use the same SQLConnection as other sql command? WHat this program does is it parses in a file to a list called individuals and from that I just want to update the fields in SQL. The first SQL was already written in an seems to execute correctly now I need to do the UpdtHasInv SQL and actually get the code to perform the update is where I need help.
Heres what I have so far:
static void InsertCustomData(Collection<Individuals> individuals)
{
#region
string insertsql = "";
insertsql = #"Insert into IND (IND_ID, ITEM_NAME, INDL_ITEM_VALUE, XPTIM)
select IND_ID, '{0}' as Item, '{1}' as val, (current timestamp - curtime)"
FROM IND
where IN = #IN";
// this is SQL I added for update
**UpdtHasInv = #"UPDATE Ind
SET HAS_I = -1
WHERE IN = #IN";**
#endregion
using (DB2Connection conn = DB2Helper.getConnection())
{
DB2Command cmd = conn.CreateCommand();
cmd.CommandTimeout = 600;
cmd.Parameters.Add("#IN", "");
if (conn.State == ConnectionState.Closed)
{
conn.Open();
}
foreach (Individuals individual in individuals)
{
cmd.Parameters["#IN"].Value = individual.In;
foreach (CustomData customData in individual.CustomData)
{
cmd.CommandText = string.Format(insertIndsql, customData.Data.Key, customData.Data.Value);
Could I just write : 'cmd.CommandText = UpdtIsInv;' after these lines:
foreach (Individuals individual in individuals)
{
cmd.Parameters["#IN"].Value = individual.in
You could simply append your UPDATE after the INSERT using a semicolon.
insertIndsql = #"
INSERT INTO IND (IND_ID, ITEM_NAME, INDL_ITEM_VALUE, XPTIMESTAMP)
SELECT INDIVIDUAL_ID, '{0}' as Item, '{1}' as val, (current timestamp - curtime)
FROM IND
WHERE TIN = #TIN;
UPDATE DB2INST1.Individual
SET HAS_INVESTMENT = -1
WHERE TIN = #TIN;";
When executed, both statements will be executed as part of the same command.