Updating the value in column in SQLite - c#

I want to pass a column2 to a function and update column3 with output of function. I have made func function to calculae the output. When i run the program
it only takes last value as input and outputs all columns with same value.What am i doing wrong?
sqlite1 = new SQLiteConnection("DataSource = D:/datab.db;version=3");
sqlite1.Open();
string query1 = "select * from ramrotable";
SQLiteCommand cmd = new SQLiteCommand(query1, sqlite1);
SQLiteDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
Console.WriteLine("Age::" + reader["age"]);
//int data = Convert.ToInt16(reader["age"]);
string tempquery = string.Format("UPDATE ramrotable SET num =
func({0})",reader["age"]);
cmd = new SQLiteCommand(tempquery, sqlite1);
cmd.ExecuteNonQuery();
}
string query4 = "select * from ramrotable";
cmd = new SQLiteCommand(query4, sqlite1);
reader = cmd.ExecuteReader();
while (reader.Read())
{
Console.WriteLine("Name: " + reader["name"] + " Age: " +
reader["age"] + " Num: " + reader["num"]);
}

You need to use a WHERE clause to tell SQLite which record to update exactly. Otherwise all records will be affected. Please make sure that in the WHERE clause you use a column (or a combination of columns) the identify the record uniquely!
Ideally, every record will have an ID column that contains a unique value and is the Primary Key.
I understand from the comments to the question that you actually want to update the value of the num column depending on a value from the age column of the same record, for all the records in the table.
To do this, you neither need to fetch all the records nor do you need to loop. All you need to do is invoke the following statement:
UPDATE ramrotable SET num = func(age)
This takes the value of the age column, passes it to func and sets the result as the new value for the num column for each record in the table.
So all of what you've written above can be shortened to
sqlite1 = new SQLiteConnection("DataSource = D:/datab.db;version=3");
sqlite1.Open();
cmd = new SQLiteCommand("UPDATE ramrotable SET num = func(age)", sqlite1);
cmd.ExecuteNonQuery();

When using
string tempquery = string.Format("UPDATE ramrotable SET num =
func({0})",reader["age"]);
you are updating each row with current func(age) value.
For updating each row with exact value you should use single command outside of the while loop:
string updatequery = "UPDATE ramrotable SET num = func(age)";
cmd = new SQLiteCommand(updatequery, sqlite1);
cmd.ExecuteNonQuery();

Related

Auto generate and AutoIncrement ID in C# when trying to add new record to database

I'm using this code to select the maxID from a database table and each time I want to add a new record, the autogenerated ID is not the last one +1.
public formularAddCompanie()
{
InitializeComponent();
try
{
string cs = "Data Source=CODRINMA\\CODRINMA;Initial Catalog=TrafficManager;Integrated Security=True";
string select = "SELECT max(IDCompanie) FROM Companii";
using (SqlConnection con = new SqlConnection(cs))
{
con.Open();
SqlCommand cmd2 = new SqlCommand(select, con);
SqlDataReader sda = cmd2.ExecuteReader();
DataTable idmax = new DataTable("idmax");
idmax.Load(sda);
if (idmax.Rows[0][0].ToString().Trim() == "") { txtID.Text = "1"; }
else { txtID.Text = (int.Parse(idmax.Rows[0][0] .ToString() + 1).ToString()); }
}
}
catch (Exception er) { MessageBox.Show(er.Message); }
}
The table from where the selection is made, looks like this:
IDCompany Name Address City RegNo
1 A Street NY 123
Each time I want to add a new record, the autogenerated ID is like this: 11, 111, 1111. It takes the last ID and add another 1 next to it. What am I missing?
Interestingly, note that
string a = "The meaning of life is " + 42;
converts 42 to a string, creating the result
a == "The meaning of life is 42"
Look at this code:
(int.Parse(idmax.Rows[0][0] .ToString() + 1).ToString()); }
You are converting idmax.Rows[0][0] to a string and adding +1 to the end of the string rather than to an integer value. Try
(int.Parse(idmax.Rows[0][0].ToString()) + 1).ToString(); }
Note that idmax.Rows[0][0] should already have an integer in it (as pointed out in the comments). If that's the case, you can simplify to
(idmax.Rows[0][0] + 1).ToString(); }
idmax.Rows[0][0].ToString() + 1 produces string, not int.
You can try
txtID.Text = (Convert.ToInt32(idmax.Rows[0][0]) + 1).ToString();
I just add this because it seems that none cares about the weakness of the code posted by the poster.
First the MAX function is not reliable if you want to find the next autoincrement value that will be assigned to an ID column. Concurrency could wreak havoc with any schema that use MAX. Just suppose that another user has already retrieved the MAX for its own INSERT operation, then depending on the relative speed of the two computers you or the other user will insert a duplicate value for the IDCompany field.
The only correct way to do this common task is to use the IDENTITY property for the column IDCompany and when you need to insert a new record you should write something like this
try
{
string insert = "INSERT INTO Companii (Name,Address,City,RegNo)
VALUES(#name,#address,#city,#regno);
SELECT SCOPE_IDENTITY()";
using (SqlConnection con = new SqlConnection(cs))
using (SqlCommand cmd = new SqlCommand(insert, con))
{
con.Open();
cmd.Parameters.Add("#name", SqlDbType.NVarChar).Value = txtBoxCity.Text;
.... and on for the other parameters ....
int companyID = Convert.ToInt32(cmd.ExecuteScalar());
... work with the just added company if required
}
}
catch (Exception er)
{ MessageBox.Show(er.Message); }
SCOPE_IDENTITY will return the last identity value inserted into an identity column in the same scope and in this context scope means the connection used by your command.
In any case, if the MAX approach is still required then the code could be simplified a lot using a modified query and SqlCommand.ExecuteScalar instead of building an SqlDataReader, filling a datatable, trying to parse the result with ifs
string getMax = #"select COALESCE(MAX(IDCompany), 0) + 1 AS maxPlusOne
from Companii"
using(SqlConnection cnn = new SqlConnection(.....))
using(SqlCommand cmd = new SqlCommand(getMax, cnn))
{
cnn.Open();
int nextCompanyID = Convert.ToInt32(cmd.ExecuteScalar());
}
The COALESCE function checks the result of the MAX function and if it is NULL returns the second parameter (here 0), then just increment by 1 to get the next MAX directly from the database. ExecuteScalar will do the call returning just the maxPlusOne alias field
try this snippet:
Convert Your String into Int. String with + operator will con-cat and with int it will add numbers.
if (idmax.Rows[0][0].ToString().Trim() == "") { txtID.Text = "1"; }
else {
txtID.Text = Convert.ToString(Convert.ToInt32(idmax.Rows[0][0] .ToString())+1); }
Try This one, my id format is USR001.The code will generate auto id based on the last id inside the database. If the last id in the database is USR001, the the code will generate USR002 and put the id to the textbox
con.Open();
string sqlQuery = "SELECT TOP 1 kode_user from USERADM order by kode_user desc";
SqlCommand cmd = new SqlCommand(sqlQuery, con);
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
string input = dr["kode_user"].ToString();
string angka = input.Substring(input.Length - Math.Min(3, input.Length));
int number = Convert.ToInt32(angka);
number += 1;
string str = number.ToString("D3");
txtKodeUser.Text = "USR" + str;
}
con.Close();

What is the correct way to get created row Id on Oracle using the RETURNING INTO clause in c# and OCI:

I have the following statement to insert row and get the Id or row inserted:
int returnId;
string sql = "INSERT INTO table_name (a, b, c) VALUES (1, 2, 3) RETURNING ID INTO :returnId;";
OracleCommand command = conn.CreateCommand();
command.CommandText = sql;
Console.WriteLine ("The row created has a Id = " + returnId);
This doesn´t work. I tried also the following variation:
string sql = "INSERT INTO table_name (a, b, c) VALUES (1, 2, 3) RETURNING ID;";
OracleCommand command = conn.CreateCommand();
command.CommandText = sql;
int rowsUpdated = command.ExecuteNonQuery();
if (rowsUpdated != 1)
return;
OracleDataReader reader = command.ExecuteReader();
while (reader.Read())
{
string id = (string)reader["ID"];
Console.WriteLine ("The row created has a Id = " + returnId);
}
This this inserts 2 rows into database, and the reader is empty.
So, what´s the correct way to programatically use RETURNING INTO clause to get the created row Id.
Thanks for any help.
your returning clause is fine but your C# code is all wrong. You need to use the Parameters property - read here: http://msdn.microsoft.com/en-us/library/system.data.oracleclient.oraclecommand.parameters%28v=vs.110%29.aspx
e.g.:
command.Parameters.Add("returnId", OracleType.Number).Direction = ParameterDirection.Output;
after executing your query check command.Parameters["returnId"].Value

Long Query from OracleDB

I have created a query to oracle db
Dictionary<decimal, decimal> Dict = new Dictionary<decimal, decimal>();
string strSelectIdWork = "SELECT COLUMN FROM my_tb WHERE ROW='" + Row + "'";
dataAdapter.Fill(ds, "my_tb");
foreach (DataRow row in ds.Tables["my_tb"].Rows)
{
foreach (DataColumn column in ds.Tables["my_tb"].Columns)
{
Dict.Add(Dict.Count + 1, Convert.ToDecimal(row[column]));
}
}
foreach (decimal someVar in Dict.Values)
{
OleDbCommand command = myAccessConn.CreateCommand();
OleDbTransaction trans = myAccessConn.BeginTransaction();
command.Transaction = trans;
command.CommandText = "SELECT COLUMN FROM my_tb2 WHERE ROW='" + someVar + "'";
command.ExecuteNonQuery();
nb = Convert.ToString(command.ExecuteScalar());
comboBox2.Items.Add(nb;
trans.Commit();
}
It's working, but it takes a long time to execute and I have many queries in my function.
How can I change the code to reduce the time of the request?
I'm not too sure what you are trying to achieve, but do you realize that you are making countless connections to the database here?...
foreach (decimal someVar in Dict.Values)
{
OleDbCommand command = myAccessConn.CreateCommand();
OleDbTransaction trans = myAccessConn.BeginTransaction();
command.Transaction = trans;
command.CommandText = "SELECT COLUMN FROM my_tb2 WHERE ROW='" + someVar + "'";
command.ExecuteNonQuery();
nb = Convert.ToString(command.ExecuteScalar());
comboBox2.Items.Add(nb;
trans.Commit();
}
Whatever the total rows returned from this query...
"SELECT COLUMN FROM my_tb WHERE ROW='" + Row + "'"
will be equivalent to the total of database connections you will be opening...not to mentioned the total amount of transactions you will open as well. Do you really need to run a transaction for this select query?
Why don't you retrieve all the dictionary values into an array...
var values = Dict.Values.ToArray();
then join the values into a CSV string....
var #param = string.Join(",", values);
and pass this #params string to an IN clause
command.CommandText = "SELECT COLUMN FROM my_tb2 WHERE ROW IN(" + #param + ")";
var reader = command.ExecuteReader();
while(reader.Read())
{
comboBox2.Items.Add(reader["COLUMN"].ToString());
}
I'm omitting some details for clarity but if you need some clarifications, let me know
You really need to be using Bind Variables in these kind of situations. Oracle will parse each occurance of your query as a whole new query, which will slow things down considerably. I'm not a developer so I can't tell you how to apply this to C#, but you should start by reading this helpful article on the topic:
http://www.akadia.com/services/ora_bind_variables.html

Get the difference on each date and insert into database

I have a table with a (IDcolumn, int), (Differencecolumn, int) and (Datecolumn DateTime) that contains different dates.
And a method that compute the difference between the dates that ignores the weekends.
public static double GetBusinessDays(DateTime startD, DateTime endD)
{
double calcBusinessDays =
1 + ((endD - startD).TotalDays * 5 -
(startD.DayOfWeek - endD.DayOfWeek) * 2) / 7;
if ((int)endD.DayOfWeek == 6) calcBusinessDays--;
if ((int)startD.DayOfWeek == 0) calcBusinessDays--;
return calcBusinessDays;
}
I want to get each GetBusinessDays value on each Datecolumn from date today.
And insert it to each corresponding Differencecolumn.
For example
ID Date Difference
1 4-22-2013
2 4-23-2013
3 4-24-2013
Assume that the date today is 4-28-2013. The difference must contain 6, 5, 4 respectively.
This what i have done for now but it not works :(
myDatabaseConnection.OpenConnection();
mySqlCommand.CommandType = CommandType.Text;
mySqlCommand.CommandText = "select * from Table1 where Difference IS Null";
SqlDataReader sqlreader = mySqlCommand2.ExecuteReader();
int i;
while (sqlreader.Read())
{
i = sqlreader.GetInt32(0);
double y = GetBusinessDays(sqlreader.GetDateTime(1), DateTime.Now);
string commandtext = "Update Table1 SET Difference = " + y + " Where ID = " + i + " ";
mySqlCommand.CommandText = " " + commandtext + " ";
}
myDatabaseConnection.CloseConnection();
First and foremost, you appear to be missing a call to mySqlCommand.ExecuteNonQuery(). That should go inside your while loop, after you assign to mySqlCommand.CommandText.
You'll also need to use a separate SqlCommand object for the Update query, as the existing one is being used by the SqlDataReader as you iterate through the result set. I also recommend always using parameterized SQL. Putting these two points together:
SqlCommand myUpdateCmd = new SqlCommand("Update [Table1] SET [Difference] = #Difference Where [ID] = #ID", myDatabaseConnection);
myUpdateCmd.Parameters.AddWithValue("#ID", i);
myUpdateCmd.Parameters.AddWithValue("#Difference", (int)y);
myUpdateCmd.ExecuteNonQuery();
Beyond that, here are some suggestions that you may find helpful:
You seem to be assuming that the Difference column will initially be NULL, but you didn't show the exact definition for Table1. Make sure the Difference column allows NULL values, and that there is no default value set (or that the default value is NULL).
To guarantee that the columns are in the order you expect, I recommend doing one of the following.
Specify the column names in your select query:
select [id], [date], [difference] from [Table1] where [difference] is null
When retrieving a column's value through the SqlDataReader, don't hard-code the column's ordinal (0, 1, 2, ...). Instead, use the GetOrdinal() method to dynamically determine the column's ordinal. For example:
i = sqlreader.GetInt32(sqlreader.GetOrdinal("id"));
Almost all of these ADO.NET objects are IDisposable. As such, it's generally best to make use of C#'s using statement to guarantee that these objects will be cleaned up.
using (SqlConnection myDatabaseConnection = new SqlConnection(myConnectionString))
{
// code that uses myDatabaseConnection goes here
}
Putting all of these points together, we end up with:
using (SqlConnection myDatabaseConnection = new SqlConnection("DB connection string goes here"))
{
myDatabaseConnection.Open();
using (SqlCommand mySqlCommand = new SqlCommand("select [id], [difference], [date] from [Table1] where [difference] is null", myDatabaseConnection))
using (SqlDataReader sqlreader = mySqlCommand.ExecuteReader())
using (SqlCommand myUpdateCmd = new SqlCommand("update [Table1] set [difference] = #difference where [id] = #id", myDatabaseConnection))
{
int i;
myUpdateCmd.Parameters.Add("#id", SqlDbType.Int);
myUpdateCmd.Parameters.Add("#difference", SqlDbType.Int);
while (sqlreader.Read())
{
i = sqlreader.GetInt32(sqlreader.GetOrdinal("id"));
double y = GetBusinessDays(sqlreader.GetDateTime(sqlreader.GetOrdinal("date")), DateTime.Now);
myUpdateCmd.Parameters["#id"].Value = i;
myUpdateCmd.Parameters["#difference"].Value = (int)y;
myUpdateCmd.ExecuteNonQuery();
}
}
}
Update: Karlx mentioned that he had to enable Multiple Active Result Sets on the database connection before his application would work. To do this, add "MultipleActiveResultSets=True" to your database connection string.

use one reader object to read more than one result sets from sql database

Can i use the same reader to read results from two result sets?
string checktrigger =
"select name from sys.triggers where name = 'Insertion_in_ITEMS_table' " +
"select object_name(parent_obj)from sysobjects where id =
object_id('Insertion_in_ITEMS_table')";
SqlCommand check_cmd = new SqlCommand(checktrigger, _conn);
SqlDataReader check_reader = check_cmd.ExecuteReader();
string triggername = check_reader.GetString(0);
string tablename = check_reader.GetString(1);
if (triggername.Length != 0)
{
MessageBox.Show(triggername + "CREATED SUCCESSFULLY" + "ON TABLE " + triggername + tablename);
}
this is giving error that index out of bounds
should i use array? to return the result set
User reader.Read() to get the next record and reader.NextResult() to switch to the next result in the result set.
while (check_reader.Read())
{
// get rows from the first select
}
// switch to next
check_reader.NextResult();
while (check_reader.Read())
{
// get rows from the second select
}

Categories

Resources