I have a table in SQL server:
| date_Tim| Machine|Case_wrong|
|:---------|:--------:|:----------:|
|07/03/21 16:53:PM|Test1|1|
|07/03/21 16:58:PM|Test1|1|
|07/03/21 16:59:PM|Test1|1|
|07/03/21 16:58:PM|Test2|1|
|07/03/21 16:59:PM|Test2|1|
|07/03/21 17:00:PM|Test2|1|
|07/03/21 17:01:PM|Test3|1|
|08/03/21 16:58:PM|Test3|1|
|08/03/21 16:58:PM|Test2|1|
I want to sum column machine All machine from date 07/03/22 and fill to chart
I try code
private void loadchart()
{
var Today = DateTime.Now.ToString("dd/MM/yy");
ChartTop.Series[0].Points.Clear();
ChartTop.ChartAreas["ChartArea1"].AxisX.Interval = 1;
string constring = ConfigurationManager.ConnectionStrings["Connstring"].ConnectionString;
SqlConnection con = new SqlConnection(constring);
SqlCommand sqlCmd = new SqlCommand();
sqlCmd.Connection = con;
sqlCmd.CommandType = CommandType.Text;
SqlDataAdapter sqlDataAdap = new SqlDataAdapter(sqlCmd);
try
{
sqlCmd.CommandText = sqlCmd.CommandText = "SELECT TOP 10 Machine, Sum(Case_wrong) as Case_wrong FROM tbl_Count_" + cbWorkcell.Text + " group by Machine order by SUM(Case_wrong)";
DataSet dtRecord = new DataSet();
sqlDataAdap.Fill(dtRecord);
ChartTop.DataSource = dtRecord;
//set the member of the chart data source used to data bind to the X-values of the series
ChartTop.Series["Series1"].XValueMember = "Machine";
//set the member columns of the chart data source used to data bind to the X-values of the series
ChartTop.Series["Series1"].YValueMembers = "Case_wrong";
// ChartTop.Series[0].ChartType = SeriesChartType.Pie;
con.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
it works but it takes all the data in my table for calculation. is there a way to filter the data by date and sum there?
Please help me! Thanks.
What appears is that date_Tim is a datetime feild , if thats the case then you need a where clause added to your query , I am assuming that the date you mentioned (07/03/22) is DD/MM/YY based on that the query needs to be updated to add the clause as below
"SELECT TOP 10 Machine, Sum(Case_wrong) as Case_wrong FROM tbl_Count_" + cbWorkcell.Text + " WHERE date_Tim >='2022-03-07 00:00:00.000' group by Machine order by SUM(Case_wrong)"
Please note #madreflection has pointed out critical errors, please fix them more details about SQL injection here
Edit 1:
In case you are just looking for a specific day
"SELECT TOP 10 Machine, Sum(Case_wrong) as Case_wrong FROM tbl_Count_" + cbWorkcell.Text + " WHERE CAST(date_Tim AS DATE) ='2022-03-07' group by Machine order by SUM(Case_wrong)"
In case you are looking for the current date
"SELECT TOP 10 Machine, Sum(Case_wrong) as Case_wrong FROM tbl_Count_" + cbWorkcell.Text + " WHERE CAST(date_Tim AS DATE) = GETDATE() group by Machine order by SUM(Case_wrong)"
Related
I am letting the user able to delete a specific record in a SQL table. The problem is that I want to set the id(automatically) to the last id sequence presented into the db after the deletion. ex(delete item 14,when I add another item the id of that item won't be 15 but 14 because after the delete I've reset the id to 13 which is the last one after the delete)
private void btnCanc_Click(object sender, RoutedEventArgs e)
{
sqliteCon.Open();
try
{
string Test = null;//estrazione1
SqlCommand q = new SqlCommand("DELETE FROM tabSE WHERE idSE =" + txtIDL.Text.ToString(), sqliteCon);
//string q = "DELETE FROM tabSE WHERE idSE =" + txtIDL.Text.ToString();
SqlCommand q1 = new SqlCommand("DELETE FROM tabL WHERE idL =" + txtIDL.Text.ToString(), sqliteCon);
//string q1 = "DELETE FROM tabL WHERE idL =" + txtIDL.Text.ToString();
SqlCommand q2 = new SqlCommand("DELETE FROM tabSD WHERE id =" + txtIDL.Text.ToString(), sqliteCon);
//string q2 = "DELETE FROM tabSD WHERE id =" + txtIDL.Text.ToString();
q.ExecuteNonQuery();
q1.ExecuteNonQuery();
q2.ExecuteNonQuery();
SqlCommand m = new SqlCommand("SELECT idL FROm tabL", sqliteCon);
SqlDataReader idLRdr = null;//estrazione2
idLRdr = m.ExecuteReader();//estrazione3
while (idLRdr.Read())//estrazione4
{
Test = idLRdr["idL"].ToString();//estrazione5
}
SqlCommand r = new SqlCommand("DBCC CHECKIDENT(tabL,tabSE,tabSD,RESEED,'" + Test + "')", sqliteCon);
r.ExecuteNonQuery();
SqlCommand r1 = new SqlCommand("DBCC CHECKIDENT(tabL,RESEED,'" + Test + "')", sqliteCon);
r1.ExecuteNonQuery();
SqlCommand r2 = new SqlCommand("DBCC CHECKIDENT(tabSE,RESEED,'" + Test + "')", sqliteCon);
r2.ExecuteNonQuery();
SqlCommand r3 = new SqlCommand("DBCC CHECKIDENT(tabSD,RESEED,'" + Test + "')", sqliteCon);
r3.ExecuteNonQuery();
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message);
}
MessageBox.Show("Dato Cancellato Correttamente");
sqliteCon.Close();
}
code improved but it update the value of the id of the table but not the real id of each table(idL,idSE,id)(those are my custom ids)
OK I'VE MADE MY TESTS,THE PROBLEM IS THAT THE ID'S OF EACH TABLE(idL(TABLE tabL),idSE(TABLE tabSE),id(TABLE tabSD))AREN'T UPDATED BY MY CODE DBCC WHILE THE ID'S OF EACH TABLE(THOSE WHICH AREN'T CUSTOM MADE) ARE UPDATE AUTOMATICALLY... I NEED TO UPDATE idL,idSE,id
Of course the first problem is the fact that you don't execute the commands, but there are a lot of things that could be improved in your code. First and foremost is the concatenation of strings to build a sql command. This leads to problems with parsing and to the dangerous Sql Injection trick used to hack a databases. I have changed your code to use a parameter and avoid these problems.
The second improvement is given by the ability to execute batch commands. In other words you can put all your command texts in a single string and separate each one using a semicolon. Then just execute the command only one time and everything will be executed by the database engine.
But the real problem in your code is the DBCC CheckIdentity RESEED part. This part requires you to know which value to set as the new Identity because the RESEED option without a new value works only if the next identity value is lower than the current max value in the IDENTITY column, moreover this could be done safely only if you have exclusive access to the database (I mean, none is adding records to these tables while you get the MAX value for the ID)
sqliteCon.Open();
try
{
string sqlText = #"DELETE FROM tabStoreExec WHERE idSE = #idse;
DELETE FROM tabList WHERE idL = #idse;
DELETE FROM tabStoricoDetail WHERE id = #idse";
SqlCommand q = new SqlCommand(sqlText, sqliteCon);
q.Parameters.Add("#idse", SqlDbType.Int).Value = Convert.ToInt32(txtIDL.Text);
q.ExecuteNonQuery();
// This is the point where you change the identity.
// To minimize concurrency problems we execute a stored procedure instead
sqlText = "ResetIdentity";
q.CommandText = sqlText;
q.CommandType = CommandType.StoredProcedure;
q.Parameters.Clear();
q.ExecuteNonQuery();
MessageBox.Show("Dato Cancellato Correttamente");
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message);
}
sqliteCon.Close();
This is the possible code for your stored procedure, note that I don't know what is the name of the IDENTITY column in your tables. For this example I have used always id as the name for the IDENTITY column
create procedure ResetIdentity
as
begin
declare #maxval integer
set #maxval = (select MAX(id) from tabStoreExec);
dbcc checkident('tabStoreExec', RESEED, #maxval);
set #maxval = (select MAX(id) from tabStoricoDetail);
dbcc checkident('tabStoricoDetail', RESEED, #maxval);
set #maxval = (select MAX(id) from tabList);
dbcc checkident('tabList', RESEED, #maxval);
end
There is another improvement to your code and it is related to the using statement to create disposable objects like the database connection. The correct usage of such objects should be something like this
using(SqlConnection sqlConn = new SqlConnection(......))
{
sqlConn.Open();
.... do you database code here ....
} // This will close and dispose the connection
i will go as well with what #Steve said , the ID here is for the table (PK,FK)relation , why don't just add another field of sequential numbers that you update using LINQ as desired . and also your code is missing the query execution command ,
SqlCommand q = new SqlCommand("DELETE FROM tabStoreExec WHERE idSE =" +
txtIDL.Text.ToString(), sqliteCon);
//string q = "DELETE FROM tabStoreExec WHERE idSE =" + txtIDL.Text.ToString();
q.ExecuteNonQuery();
OR
con.Open();
using (SqlCommand q= new SqlCommand("DELETE FROM tabStoreExec WHERE idSE =" + txtIDL.Text.ToString(), sqliteCon))
{
q.ExecuteNonQuery();
}
con.Close();
I have to update multiple records in SQL Server table from C#. Below are the steps I have to follow and below is the code.
The code is working but the process is taking much longer than expected.
I need a quick way to update 10000 records, not sure whether Bulk Copy would work for Update.
I have seen the other answers which has Bulk insert to temp and then update..But that update has a single statement and here I need to update the records in DB based on Excel data and for this I have to loop each excel record.So how can I achieve faster update.
1) Read the Excel Data and copied the data into a data table
string strDirectory = string. Empty;
strDirectory = System.IO.Directory.GetCurrentDirectory() + "\\" + "Filename.xlsx";
string Connection String = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source = " + strDirectory + "; Extended Properties = \"Excel 12.0;HDR=YES;IMEX=1\"";
using (OleDbConnection conn = new OleDbConnection(Connection String))
{
conn.Open();
DataTable schemaTable = conn.GetOleDbSchemaTableOleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
DataRow schemaRow = schemaTable. Rows[0];
string sheet = schemaRow["TABLE_NAME"].ToString();
string query = "SELECT * FROM [" + sheet + "]";
OleDbDataAdapter daexcel = new OleDbDataAdapter(query, conn);
daexcel.Fill(dt);
conn.Close();
}
2) Doing some manipulations on datatable data before updating into table.
string strsqlst = string. Empty;
using (SqlConnection sqlConn = new SqlConnection(Connectionstring))
{
sqlConn.Open();
SqlCommand cmd;
StringBuilder sb = new StringBuilder();
sb.AppendLine("DataTable content:");
foreach (DataRow row in dt.Rows)
{
if (row.ItemArray[0].ToString() == "")
break;
strsqlst = "Update table Set col1= " + row.ItemArray[4].ToString() + " ,col2= " + row.ItemArray[5].ToString() + " where <Condition>'";
cmd = new SqlCommand(strsqlst, sqlConn);
cmd.CommandType = CommandType.Text;
cmd.ExecuteNonQuery();
}
sqlConn.Close();
}
The SqlCommand can be a whole SQL batch and is not limited to a single statement. So you can create a single large batch with 10,000 UPDATE statements, or divide it into for example 20 batches of 500 each.
In other words, you can create a single command with CommandText like this:
UPDATE [T] SET Col1='Value1', Col2='Value2' WHERE [Id] = 1;
...
UPDATE [T] SET Col1='Value999', Col2='Value1000' WHERE [Id] = 500;
That said, you should use parameters for all data values (to ensure SQL injection is not possible).
If you want to handle any errors (updates failing due to invalid data) you will need something a bit more sophisticated.
I have written a program about getting data from postgresql by c#. I have run the program for a monthly and it run perfect. However, it suddenly cannot work today.
Here is the SQL code I use:
select count(call_id) , dt,hr,mn from ( select i.call_id,a.dt,hr,mn from
(SELECT call_id ,to_char("event_Time" ,'yyyy-MM-dd') as dt, to_char(extract(hour
from "event_Time"),'FM00') as hr ,to_char(floor(extract(minute from
"event_Time")/30)*30,'FM00') as mn from ivr_event where "event_Time" between
'2014-2-11 00:00:00' and '2014-2-11 23:59:59' and status='playGreeting' and
stage='InqiryMenu' group by dt,hr,mn,call_id) a,ivr_event i where a.call_id =
i.call_id and status='getDigits' and stage='Language' and click ='3' and
"event_Time" between '2014-2-11 00:00:00' and '2014-2-11 23:59:59' group by
i.call_id,dt,hr,mn ) result group by dt,hr,mn order by dt,hr,mn
Here is the C# code to select query and return an arraylist
DataSet ds = new DataSet();
DataTable dt = new DataTable();
String connstring = "Server=" + dataSource
+ ";Port=" + port + ";" + "User Id=" + userID
+ ";Password=" + password + ";Database=" + databaseName +
";CommandTimeout=0;";
NpgsqlConnection conn = new NpgsqlConnection(connstring);
conn.Open();
NpgsqlDataAdapter da = new NpgsqlDataAdapter(sqlStatement, conn);
ds.Reset();
// filling DataSet with result from NpgsqlDataAdapter
da.Fill(ds);
// since it C# DataSet can handle multiple tables, we will select first
dt = ds.Tables[0];
foreach (DataRow row in dt.Rows)
{
temp = "";
foreach (var item in row.ItemArray)
{
temp += item + ";";
}
if (row.ItemArray.Length >= 1)
temp = temp.Substring(0, temp.Length - 1);
result.Add(temp);
}
conn.Close();
The program is getting the multiple counts with different WHERE clause within 1 hour by only 1 SQL.
Then, I loop for 24 times to get the whole day counts.
It is okay for almost a month. However, when I use the same program without changing anything today, it seems always waiting the result by nothing I get. I only can end the process by stop the postgresql services(I have set no timeout).
And we got the following exception:
System.NullReferenceException:Object reference not set to an instance.
A very strange case is when I choose an very old data, it is okay. When I choose last week data, it failed. However, I have use the same sql a few days ago and it worked!
Any suggestions for me? Thank you very much!
P.S. sorry that the sql is updated. here is the real SQL that can be run
Ok, I have been having a problem the last few days with my database not updating. I can read the data fine and I'm not getting any exceptions either. I'm trying to update the database then I try to read values again after the update (during same run), and they still hold the original values, so it doesn't seem to be an issue with the database being copied to another folder (I'm using Copy if newer yet neither database is being updated).
Here is the code I'm using. As you can see I tried a few different approaches, none of which worked yet.
public void UpdateDatabaseInStock(string itemName, string tableName)
{
DataSet data = new DataSet("Items");
int val;
//get the file path to the database as a string
string dbfile =
new System.IO.FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).DirectoryName +
"\\Database\\GameData.sdf";
//connect to the database
using (SqlCeConnection cntn = new SqlCeConnection("datasource=" + dbfile))
{
//create an adapter to pull all data from the table
using (SqlCeDataAdapter adpt = new SqlCeDataAdapter
("SELECT * FROM " + tableName + " WHERE Name LIKE '%" + itemName + "%'", cntn))
{
//put the data into a DataSet
adpt.Fill(data);
cntn.Close();
}
//fill the data from the Items table into a DataTable to return.
DataTable itemTable = data.Tables[0];
DataRow a = itemTable.Rows[0];
val = (short)a.ItemArray[3] - 1;
dbfile = "";
data.Dispose();
itemTable.Dispose();
SqlCeCommand cmd = new SqlCeCommand();
cmd.Connection = cntn;
cntn.Open();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "UPDATE " + tableName + " SET [In Stock] = #Value WHERE [Name] = '#ItemName'";
//cmd.Parameters.Add("#Value", SqlDbType.SmallInt);
//cmd.Parameters["#Value"].Value = val;
//cmd.Parameters.Add("#ItemName", SqlDbType.NChar, 75);
//cmd.Parameters["#ItemName"].Value = itemName;
cmd.Parameters.AddWithValue("#Value", val);
cmd.Parameters.AddWithValue("#ItemName", itemName);
cmd.ExecuteNonQuery();
//close the conenction
cntn.Close();
cmd.Dispose();
}
}
Any ideas to get it to actually update?
Just a hunch (can't corroborate this on msdn): could it be that using nchar(75) adds spaces to the parameter, thereby causing the WHERE clause to fail?
I'm facing a problem where every time I refresh my page, the loan paid will increase by 500. I understand that my logic is wrong, after 1 month from the loan application date, the 'loanPaid' will increase by 500 but what I want to happen is every next month it will increase by $500. If anyone who can help me with the logic. I would appreciate it. I was thinking of using some loop but not sure which one and how. I'm a freshman student only so please pardon my coding style. Thank you
public class LoanDAL
{
string connString = ConfigurationManager.ConnectionStrings["Oakhorizons"].ToString();
public LoanDAL()
{
//
// TODO: Add constructor logic here
//
}
public DataTable getAllLoanInfoDT()
{
using (SqlConnection conn = new SqlConnection(connString))
{
DataTable dt = new DataTable();
SqlCommand cmd2 = new SqlCommand();
cmd2.Connection = conn;
// cmd.CommandType = CommandType.StoredProcedure;
cmd2.CommandText = "SELECT DISTINCT purchaseDate FROM LoanPortfolio WHERE (custID LIKE 'OH00002') AND (loanType LIKE 'Personal Loan')";
cmd2.Parameters.AddWithValue("#custID", "OH00002");
cmd2.Parameters.AddWithValue("#loanType", "Personal Loan");
conn.Open();
string custID = "OH00002";
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = cmd2;
da.Fill(dt);
int iMonthNo = int.Parse(System.DateTime.Now.Month.ToString());
DateTime dtDate = new DateTime(2000, iMonthNo, 1);
double dMonthNow = Double.Parse(dtDate.ToString("MM"));
LoanTableAdapters.LoanPortfolioTableAdapter loanAdapter = new LoanPortfolioTableAdapter();
string LoanDate = loanAdapter.RetrieveData(custID.ToString()).ToString();
string month = dt.ToString();
double dLoanDate = Double.Parse(LoanDate.Substring(3, 2));
if (dMonthNow > dLoanDate)
{
String sql = "UPDATE LoanPortfolio SET loanPaid = loanPaid + 500";
sql += "WHERE (loanType LIKE 'Personal Loan') AND (custID LIKE 'OH00002')";
cmd2.Connection = conn;
cmd2.CommandText = sql;
cmd2.ExecuteNonQuery();
}
conn.Close();
}
}
After edit:
public DataTable getAllLoanInfoDT()
{
using (SqlConnection conn = new SqlConnection(connString))
{
SqlCommand cmd2 = new SqlCommand();
cmd2.Connection = conn;
// cmd.CommandType = CommandType.StoredProcedure;
cmd2.CommandText = "SELECT DISTINCT loanUpdateDate FROM LoanPortfolio WHERE (custID LIKE 'OH00002') AND (loanType LIKE 'Personal Loan')";
cmd2.Parameters.AddWithValue("#custID", "OH00002");
cmd2.Parameters.AddWithValue("#loanType", "Personal Loan");
conn.Open();
SqlDataReader myReader = cmd2.ExecuteReader();
DateTime loanUpdateDate = Convert.ToDateTime(myReader);
DateTime currDateTime = DateTime.Now;
int loanToBeAdded = (((currDateTime.Year - loanUpdateDate.Year) * 12) + currDateTime.Month - loanUpdateDate.Month) * 500;
if (loanToBeAdded > 0)
{
String sql = "UPDATE LoanPortfolio SET loanPaid = loanPaid + " + loanToBeAdded.ToString() + ", loanUpdateDate = " + DateTime.Now.ToString();
sql += " WHERE (loanType LIKE 'Personal Loan') AND (custID LIKE 'OH00002')";
//Execute the above query here
}
conn.Close();
using (SqlDataAdapter dAd = new SqlDataAdapter("SELECT * FROM LoanPortfolio where custID like 'OH00002'", conn))
{
DataTable dTable = new DataTable();
dAd.Fill(dTable);
return dTable;
}
}
}
You have done a lot of unnecessary things, some important checks missing and some performance inhibiting mistakes also in your code but I will not point them out here since you are a freshman and you will learn gradually.
The solution to your problem should be the following
Firstly create a new column in your "LoanPortfolio" table namely "LastUpdatedLoanPaidDate". The type should be Date for this column. This will store the date when you last added $500 to "loanPaid" column.
Set this column same as "purchaseDate" when you first add a row in your "LoanPortfolio" table. So initially "purchaseDate" and "LastUpdatedLoanPaidDate" will be same.
Fetch only "LastUpdatedLoanPaidDate" instead of "purchaseDate" as
cmd2.CommandText = "SELECT DISTINCT LastUpdatedLoanPaidDate FROM LoanPortfolio WHERE (custID LIKE 'OH00002') AND (loanType LIKE 'Personal Loan')";
Assuming that there will be just 1 record fetched from the above query, The following code should add $500 to "loadPaid" column once every month
//Fetch "LastUpdatedLoanPaidDate" here
//This will be "LastUpdatedLoanPaidDate" coming from database i.e. dt[0][0].ToString(). Hard-coded here for simplicity
string strLastUpdatedLoanPaidDate = "07/29/2013";
DateTime lastUpdatedLoanPaidDate = Convert.ToDateTime(strLastUpdatedLoanPaidDate);
DateTime currDateTime = DateTime.Now;
//This will make sure that all the previous purchases are also handled and not just previous month's
//This is important when you are implementing new logic on existing data
int loanToBeAdded = (((currDateTime.Year - lastUpdatedLoanPaidDate.Year) * 12) + currDateTime.Month - lastUpdatedLoanPaidDate.Month) * 500;
//If loadToBeAdded is zero then need not update database
if (loanToBeAdded > 0)
{
String sql = "UPDATE LoanPortfolio SET loanPaid = loanPaid + " + loanToBeAdded.ToString() + ", LastUpdatedLoanPaidDate = " + DateTime.Now.ToString();
sql += " WHERE (loanType LIKE 'Personal Loan') AND (custID LIKE 'OH00002')";
//Execute the above query here
}
There might be some things which I am missing depending upon your requirement. Also the update statement might need a tweak as I have not tested it but overall this should do the trick.
Hope this helped.
Regards,
Samar
You should also indicate in your table when you increased the loan for the last time and check this value, too. You could insert a new column lastLoanIncrease in the table LoanPortFolio as char(6) and save the month and year, when you increased it. Then before increasing again check for it.
You don't need a loop.
Your issue is in your conditional if
//DateTime loanDate = new DateTime(2000, 1, 18);
DateTime loanDueDate = Foo.GetLoanDueDate(loanId);
int loanDueMonth = loanDueDate.Month;
int currentMonth = DateTime.Now.Month;
if (currentMonth > loanDueMonth)
{
// update db
loanDate.AddMonths(1);
Foo.UpdateLoanDueDate(loanId, loanDate); // increase loan due date for next month so that the conditional is true next month.
}