I am developing a gym membership program on visual studio using C# and sqlite. On every employee-log in attempt, I want the program to check for expired customers where ExpiryDate(Attribute in the table Customer) is less than today's date. this is the piece of code I used:
string sql2 = "delete from Customer where ExpiryDate<' " + DateTime.Today + " ' ";
SQLiteCommand command2 = new SQLiteCommand(sql2, m_dbConnection);
command2.ExecuteNonQuery();
Why not use SQLite built-in functions?
delete from Customer where ExpiryDate<DATE('NOW')
Aren't you missing something like
delete from Customer where ExpiryDate<DATE('NOW') AND Costumer_id=?
Use a parameterized query and your problems in converting a date to a string will evaporate
string sql2 = "delete from Customer where ExpiryDate < #td";
SQLiteCommand command2 = new SQLiteCommand(sql2, m_dbConnection);
command2.Parameters.AddWithValue("#td", DateTime.Today);
command2.ExecuteNonQuery();
Of course this is also the recommended way to avoid Sql Injections but in this case is not your main concern.
By the way, I agree with comments in your question above. Probably it is better to allow a bit of flexibility in the calculation of the deadlines. For example you could add a configuration option that set the maximum number of days allowed after the deadline and add it to the DateTime.Today value.
Related
I have a C# program and I want to run a MySQL query that insert a record. In this record I have a timestamp field that MUST BE the server timestamp, not the client timestamp.
So, I write this:
start_session = new MySqlDataAdapter("INSERT INTO CUBE_WORKTIME(ID_WORKTIME,
ID_RISORSA_FK,DATA,ORA_INIZIO_EVENTO, ORA_FINE_EVENTO,
ID_CDC_FK, CAUSALE, LAST_EVENT)
VALUES ('', '"+ idrisorsa_global + "', DATE(NOW()),NOW(),
NULL, '"+ IDCDC +"', 'Login', 'Y')", connection);
DataTable start_session_dataset = new DataTable();
start_session.Fill(start_session_dataset);
This query works well, the ID_RISORSA_FK and IDCDC fields are correct. But the date and the datetime are 0000-00-00 and 0000-00-00 00:00:00.
I also tried adding the quotes, but no effects.
Any ideas?
The first thing to change is the use of an MySqlDataAdapter to just insert a record. While this could work it is not the correct class to use for this work. A simple MySqlCommand is the correct object to use and with a lot less of infrastructure required
The second thing to change is the way in which you build your sql query. Do not concatenate together strings to form an sql command but use Parameters. This avoid Sql Injection and parsing problems.
So your code could be rewritten as
string cmdText = #"INSERT INTO CUBE_WORKTIME
(ID_RISORSA_FK,DATA,ORA_INIZIO_EVENTO, ORA_FINE_EVENTO,ID_CDC_FK,
CAUSALE, LAST_EVENT) VALUES (#risorsaID, CURDATE(), CURTIME(),
NULL, #cdcID, 'Login', 'Y')";
MySqlCommand cmd = new MySqlCommand(cmdText, connection);
cmd.Parameters.Add("#risorsaID", MySqlDbType.Int32).Value = idrisorsa_global;
cmd.Parameters.Add("#cdcID", MySqlDbType.Int32).Value = IDCDC;
int rowsInserted = cmd.ExecuteNonQuery();
So I am creating a search function within my windows form that will allow the user to search for records based on what they have entered into the textbox. I have working code for finding records based off of every filter but the DateTime one. for example:
if (customerID_rb.Checked == true)
{
sqlQuery = "SELECT CustomerID, CustomerName, Telephone, DateAndTime, Status, Description from Calls WHERE CustomerID = " + item;
//'item' is the text in the textbox
UsingCommand(conn, table, sqlQuery);
return table;
}
private static void UsingCommand(SqlConnection conn, DataTable table, string sqlQuery)
{
using (SqlCommand cmd = new SqlCommand(sqlQuery, conn))
{
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
da.Fill(table);
}
}
This will show the records containing the user entered text in the CustomerID column.
However I cannot quite figure out how to do the same but for DateTime. I know that in SQL you type 'WHERE 'DateTime = ...' but no matter how I try to reword the query string I just cannot get it to work.
The error I am getting is : 'SqlException was unhandled: An expression of non-boolean type specified in a context where a condition is expected, near 'DateAndTime'.
Code:
sqlQuery = "SELECT CustomerID, CustomerName, Telephone, DateAndTime, Status, Description from Calls WHERE DateTime DateAndTime = '" + item +"'";
I have tried with and without the DateTime and in multiple different orders, if anyone can help me with this it would be greatly appreciated!
Thanks
Edit:
Ok... I messed up a little. I wrongly assumed you would need the DateTime. However, I may have been thrown off into thinking that because I get thrown an exception if I input the date and time wrong. Thanks! :)
You should never concatenate parameters into a SQL string.
It leaves you vulnerable to SQL injection attacks.
It creates performance problems, as each unique value will create a new SQL query, having a different hash for the query, which defeats the execution-plan caching mechanism of the query engine.
For date values, the ordering of y/m/d, d/m/y, or m/d/y string formats can be different depending on the current culture settings, the OS globalization settings, and the database server's globalization settings. If they're not all in sync, then you could end up with random weirdness like mistaking January 3rd for March 1st.
Instead, you should always parameterize your queries! The query gets a placeholder for the value, and then you add the value using a separate parameter. I'm not going to give you an example here, as it takes very little time to search for this on your own and there have already been hundreds of posts on this here on S.O.
You don't need to specipy the datatype DateTime, Just write the query with column name only like
sqlQuery = "SELECT CustomerID, CustomerName, Telephone, DateAndTime, Status, Description from Calls WHERE columnname = '" + item +"'";
Generally speaking, best would be to add sql parameters, but in string format:
" ... WHERE DateAndTime = '" + item.ToString("yyyyMMdd") +"'"
The yyyyMMdd should be safe to use in all cultures.
The above is assuming, you have to search a date, not including time. Mostly times are only searched on with greater or smaller than.
Additional, if the date field itself contains time, and you only want to search the date:
".... WHERE cast(DateAndTime as date) = '" + item.ToString("yyyyMMdd") +"'"
I am writing a small program using an SQL database. The table name is StudentInfo.
I need to know the SQL code for the following
for (n=0; n<nRows; n++) {
string sql1="update StudentInfo set Position=" + n + " where <this has to be the row number>";
}
nRows is number of rows.
How can I get the row number for the above code?
best way to do this is to create a stored procedure in the database and use your code to pass the relevent information to the server
In order to accomplish this task you'll want to create a Stored Procedure or build a Query that actually accepts parameters. This will help you pass variables between, your method of concatenation will actually cause an error or become susceptible to SQL Injection attacks.
Non Parameter SQL Command:
using(SqlConnection sqlConnection = new SqlConnection("Database Connection String Here"))
{
string command =
"UPDATE Production.Product " +
"SET ListPrice = ListPrice * 2 " +
"WHERE ProductID IN " +
"(SELECT ProductID " +
"FROM Purchasing.ProductVendor" +
"WHERE BusinessEntityID = 1540);" +
using (SqlCommand sqlCommand = new SqlCommand(command, sqlConnection))
{
int execute = command.ExecuteNonQuery();
if( execute <= 0)
{
return false;
}
else
{
return true;
}
}
}
That method is essentially creation a connection, running our SQL Command, then we are using an integer to verify that it did indeed run our command successful. As you can see we simply using SQL to run our command.
The other important thing to note, you can't create a sub-query with an update; you have to create an update then run a select as the sub-query to hone in more specific data across so you can span across tables and so on.
The other alternative would be to use a parameter based query, where your passing variables between SQL and your Application.
I won't post code to that, because I believe you wrote the C# loop to demonstrate what you would like SQL to do for you. Which is only update particular rows; based on a specific criteria.
If you could post additional information I'd be more then happy to help you. But I'm just going to post what I believe you are trying to accomplish. Correct me if I'm wrong.
Im trying to get the date and the time using C# , and then insert it into a smalldatetime data type in SQL SERVER.
This is how I try to do it :
DateTime date = DateTime.Now;
sql = "INSERT INTO YTOODLE_LINKS (YTOODLE_LINKS.TASK_ID,YTOODLE_LINKS.LINK_TITLE,YTOODLE_LINKS.LINK_DESC,YTOODLE_LINKS.LINK_PATH,YTOODLE_LINKS.USER_ID,YTOODLE_LINKS.LAST_USER_EDIT)VALUES (1,'','','',2,'1',"+ date +")";
dataObj = new DataObj();
dataObj.InsertCommand(sql);
connection = new SqlConnection(conn);
connection.Open();
cmd = new SqlCommand(sql, connection);
cmd.ExecuteNonQuery();
connection.Close();
and then then it gives me : "Incorrect syntax near '16'."
I guess it refers to my current time , which is 16:15 right now..
I would suggest using parameters. cmd.Parameters.AddWithValue("#date", date.toString); The AddWithField will take care of the proper conversion.
Your InsertSQL statment becomes:
sql = "INSERT INTO YTOODLE_LINKS (YTOODLE_LINKS.TASK_ID,YTOODLE_LINKS.LINK_TITLE,YTOODLE_LINKS.LINK_DESC,YTOODLE_LINKS.LINK_PATH,YTOODLE_LINKS.USER_ID,YTOODLE_LINKS.LAST_USER_EDIT)VALUES (1,'','','',2,'1',#date)";
It doesn't work for 2 reasons:
Your date parameter needs to call date.ToString()
You must add single quotes before and after the date string is inserted in your inline query as so:
sql = "INSERT INTO YTOODLE_LINKS (YTOODLE_LINKS.TASK_ID,YTOODLE_LINKS.LINK_TITLE,YTOODLE_LINKS.LINK_DESC,
YTOODLE_LINKS.LINK_PATH,YTOODLE_LINKS.USER_ID,YTOODLE_LINKS.LAST_USER_EDIT)
VALUES (1,'','','',2,'1','"+ date +"')";
But the above strategy is not good because it exposes you to SQL Injection attacks by concatenating strings the way you are doing it and also because you have to worry about adding single quotes, etc., etc.
A better approach is to use parameters as so:
sql = "INSERT INTO YTOODLE_LINKS (YTOODLE_LINKS.TASK_ID,YTOODLE_LINKS.LINK_TITLE,YTOODLE_LINKS.LINK_DESC,
YTOODLE_LINKS.LINK_PATH,YTOODLE_LINKS.USER_ID,YTOODLE_LINKS.LAST_USER_EDIT)
VALUES (#First,#Second,#Third,#Fourth,#Fifth,#Sixth,#YourDate)";
cmd.Parameters.AddWithValue("#First", 1);
// ... and so on
cmd.Parameters.AddWithValue("#YourDate", date);
Now you don't have to worry about sql injection attacks or adding single quotes to some parameters depending on the data type, etc. It's all transparent to you, you are safer and the database engine will be able to optimize the execution plan for your query.
I have a strange problem...I have a MySql db with some columns and one of the column is date_purchased which is of type date_time.
I am using C# and made a DatetimePicker and user selects a date.
private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
{
varDate = dateTimePicker1.Value;
}
Now the problem is I have to compare the two datetimes (one from the database and one from the User) and I should display the records that are less than the date selected by the user(varDate).
select * from orders where date_purchased < = '" + varDate + "'";
I am executing this query but i am getting an exception
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '= '12/25/2011 8:01:31 PM'' at line 1
I wrote the connection string and all and I am struck at the query.
Any Help will be much appreciated...
Thanks,
Subash
You have not given any details on what you are using to run the select query; however, if you are using the connector provided by Mysql (Connector/Net) then you should be using parameters. Which would look something like this:
String sql = "select * from orders where date_purchased < #DatePurchased";
MySqlDataAdapter adapter = new MySqlDataAdapter(sql, connection);
adapter.SelectCommand.Parameters.Add("DatePurchased", MySqlType.DateTime).Value = varDate;
adapter.Fill(dataSet);
Using parameters will ensure the values are converted and will also prevent SQL Injections
Try something like where DBdatetime < "'" + vardate + "'"
One word of caution, check the formats of the two dates. I had a problem in a previous app where the DB had seconds and milliseconds, whereas the app provided just a data and set the time to 00:00. This resulted in records for the current date not showing in the result set. Thus, I had to add 23:59 to the date to get all the records for the current day.
You can retrieve the values between the two data using the following MySQL Query
SELECT * FROM table_name WHERE dbvalue < varData