I'm trying to run a query that selects all from a table that contains a DateTime. At the DateTime, it uses a DateTime variable (argument passed through the parameter), however it gives me this exception:
"FormatException was unhandled
An unhandled exception of type 'System.FormatException' occurred in mscorlib.dll
Additional information: The string was not recognized as a valid datetime"
Solutions I've tried, but didn't work:
Convert the DateTime to string
Convert the DateTime to string with correct format and then back to
DateTime again
Use the DateTime.Parse method
Use the DateTime.ParseExact method with correct format and using both
"CultureInfo.InvariantCulture" and "CreateSpecificCulture("en-GB")
Change the format to the exact same shown when running the query in
Database
As said, none of the above have worked..
The format I try to use: "MM/dd/yyyy 00:00:00"
Format shown when running query in database: "MM/dd/yyyy
hh:mm:ss:fff" (the time needs to be set to 00:00:00)
Here is the code with the connection stuff excluded:
cmd = new SqlCommand("SELECT * FROM Arithmetics "
+ "INNER JOIN ArithmeticsAndTypeIDs "
+ "ON Arithmetics.ArithmeticID = ArithmeticsAndTypeIDs.ArithmeticsID "
+ "INNER JOIN ArithmeticTypes "
+ "ON ArithmeticsAndTypeIDs.TypeID = ArithmeticTypes.TypeID "
+ "WHERE UserID = #value1 "
+ "AND TimeStamp >= '#value2' "
+ "AND TimeStamp <= '#value3'", con);
cmd.Parameters.AddWithValue("#value1", GetUserID(userLoggedIn));
cmd.Parameters.AddWithValue("#value2", DateTime.ParseExact(time.ToString(), formatString, CultureInfo.CreateSpecificCulture("en-GB").DateTimeFormat));
time = time.AddDays(1);
cmd.Parameters.AddWithValue("#value3", DateTime.ParseExact(time.ToString(), formatString, CultureInfo.CreateSpecificCulture("en-GB").DateTimeFormat));
The problem first occurs at the line: "+ "AND TimeStamp >= '#value2' ""
* And in case it makes a difference, here is the quote I use in the database which obv. works (with the variables replaced by placeholder values)
SELECT * FROM Arithmetics
INNER JOIN ArithmeticsAndTypeIDs
ON Arithmetics.ArithmeticID = ArithmeticsAndTypeIDs.ArithmeticsID
INNER JOIN ArithmeticTypes
ON ArithmeticsAndTypeIDs.TypeID = ArithmeticTypes.TypeID
WHERE UserID = 0
AND
ArithmeticTypes.TypeID = 2
AND TimeStamp >= '09-21-2016 00:00:00'
AND TimeStamp <= '09-22-2016 00:00:00'
It should be noted that "#value2" contains the value ("09-21-2016 00:00:00") (assuming that's the date that is passed as a parameter), so I know that the formatting is correct.
Any help towards fixing this issue would be greatly appreciated :)
You don't need to convert parameters to strings. That's one of the main reason they are used instead of string concatenation. As long as TimeStamp is a date-related type, your query should be :
WHERE UserID = #value1 AND TimeStamp BETWEEN #value2 and #value3
Parameter values should be passed without any conversion to string:
cmd.Parameters.AddWithValue("#value1", GetUserID(userLoggedIn));
cmd.Parameters.AddWithValue("#value2", time);
cmd.Parameters.AddWithValue("#value3", time.AddDays(1));
Parameters are passed by the driver itself in a binary form, so they don't have to be converted to text. This way you bypass any formatting or localization issues.
You also avoid SQL injection issues because the parameter values are never part of the query. Even string variables are treated as just text, they are never part of the query.
Related
On the server, the date format is mm-dd-yyyy. On my local machine, the date format is mm/dd/yyyy.
I have the following code:
DateTime FrDate, Todate;
string yy = "2020";
string mm = "04";
string dd = "01";
DateTime.TryParse(mm + "/" + dd + "/" + yy, out FrDate);
And then I am trying to run this query:
select * from helpdesk_tranactions where compl_date `= '" + FrDate.ToShortDateString() + "'
This is working fine when I run on my local machine, where the date format is mm/dd/yyyy.
However, when this code is deployed to the server, the same query is not working (since the date format is mm-dd-yyyy).
The error I get is:
The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.
The statement has been terminated.
How can I write this query in such a way that it will work regardless of the system date formatting?
Noooooooo! If you're worried about string formats for SQL date values something has already gone horribly wrong.
The column in your database should be a Date, Timestamp, or DateTime rather than varchar field, and if that's true there is no human-readable format! The data is binary. What you see is a convenience shown to you by your management tool or connection library. If you're not using one of the date types for the column column, you should fix the schema, because it really is broken.
Once you have confirmed or fixed the column so you know it is a DateTime value, you should also be using DateTime variables in the C# code. And once you're doing that, the correct way to include those values in a query looks like this (assuming MySql because of the backtick, but you should also tag the question with the correct database engine):
string sql = "select * from helpdesk_tranactions where compl_date = #compl_date";
using (var cn = new MySqlConnection("connection string here"))
using (var cmd = new MySqlCommand(sql, cn))
{
cmd.Parameters.Add("#compl_date", MySqlDbType.DateTime).Value = FrDate;
cn.Open();
// ...
}
Notice this assigns the FrDate field directly to the query parameter. There's no conversion in your code to worry about.
This technique is also the best and only truly safe way to avoid certain other types of problem with sql.
I'm trying to get the records between two dates. Specifically between the start of the day and the time now. This is my query but it doesn't work for me. I have a MYSQL database
var query = (SELECT * FROM `jobs` WHERE `EventTime` < NOW() AND `EventTime` >= '" + dtstartofday + "' AND `PersonSel` = '" + personassigned + "' AND `PersonID` = '" + id + "'");
dtstartofday is of DateTime type.
You're using string concatenation to put query values directly into your SQL string. Don't do this, for a variety of reasons, one of which is the problem you're seeing here - how c# chooses to format the date as string, according to your regional preferences, and how MySQL chooses to parse the string as a date will have direct consequences for how the query runs. As a coarse example, if your date goes in as '2/3/2000' meaning third of feb, you could be using a mysql that interprets it as second of March. Alternatively you might find that c# is representing the date as something mysql doesn't recognise as a date so it is instead converting the EventTime date to a string and then comparing the strings, which is very unlikely to work out (and slow, because of all the conversions)
Either adjust your query so the start of day calculation is done by the db, and parameterize the other elements of your query:
var query = "SELECT * FROM `jobs` WHERE `EventTime` < NOW() AND `EventTime` >= CURDATE() AND `PersonSel` = #personSel AND `PersonID` = #personID"
Or parameterize the start date properly rather than passing its value as a string:
var query = "SELECT * FROM `jobs` WHERE `EventTime` < NOW() AND `EventTime` >= #eventTimeFrom AND `PersonSel` = #personSel AND `PersonID` = #personID"
To add values for the parameters you declare its name, type and value:
var cmd = new MySqlCommand(query, connection);
cmd.Parameters.Add("#eventTime", MySqlDbType.DateTime).Value = dtstartofday; //dtstartofday is a c# datetime representing midnight today e.g DateTime.Date
cmd.Parameters.Add("#personSel", MySqlDbType.Int).Value = personassigned;
cmd.Parameters.Add("#personID", MySqlDbType.DateTime).Value = id;
var x = cmd.ExecuteReader();
It is important to appreciate the difference between having the server do the time and your local machine do the time, especially if they are in different zones, but even if their clocks drift just a little. At some moment what each machine thinks of as "today" will differ. Consider it carefully
Later, when you're bored of writing this kind of code endlessly, you can install Dapper, an extension that does it for you. Take a look at http://dapper-tutorial.net for examples of how it will reduce code like this to just two lines; query and variables in, usable objects out.
I am making project in c# .net where I am badly stuck in a database query.
I have a date column in my table of my database in which i have stored the date with datatype varchar(50) and passed (convert(varchar(8),getdate(),5) as default so it gives me a date in dd-MM-YY e.g 28-03-17.
Now the user input a month format MM and year format YY" in textbox only (NOT DAY) and in case if the user entries (month,year) are equal to month and year of database table then show the all data.
I know I have to first extract month and year from table date and then compare with user input. From searching I came to know that by using Year(DateField) I can extract year and Month Month(Date Field) from date field.
I am using below query but it isn't right at all.
"select * from table1
where YEAR(Time=convert(varchar(8),getdate(),5))='" + textBox1.Text +
"' AND MONTH(Time=convert(varchar(8),getdate(),5))='" + textBox2.Text + "'";
Where 'Time' is the name of my date field in database.The big problem is that I don't know how to compare year and month in this format that I have used.
You need to convert the value of Time column to DateTime and get the YEAR out of it.
You will get the year value in four digits, like 2017. To convert it to two digits you need to divide it by 100 using modulo operator.
//Preparing parameterized query to avoid SQL injection.
var sqlQuery = "select * from Tokens where (YEAR(Convert(datetime,Time,5)) % 100) = #year AND MONTH(Convert(datetime,Time,5)) = #month";
//Preparing command and adding parameters with the values.
var sqlCommand = new SqlCommand();
sqlCommand.CommandText = sqlQuery;
sqlCommand.Parameters.Add("#year", textBox1.Text);
sqlCommand.Parameters.Add("#month", textBox2.Text);
Now you can use this command to retrieve the data from the database.
First, sql server has a datetime data type so you should not be storing dates in your database as a string.
If you did do that, you would do something like:
select * from table1
where YEAR(Time)=" + textBox1.Text +
" AND MONTH(Time)=" + textBox2.Text;
Year and time both return ints so you do not need to delimit the text from your textboxes with a single quote.
One more thing, previous commenters are right, you should never directly take the text from a textbox and inject it into a sql string. It opens you up for sql injection attacks. Instead you should be using parameters.
Assuming that the date in the VARCHAR column is stored as dd-MM-YY (as you mentioned) then this query should work:
SELECT * FROM TABLE
WHERE SUBSTRING(-DateColumn-,4,2) = textBox1.text
AND SUBSTRING(-DateColumn-,7,2) = textBox2.text
Since you're storing the date as text, there's no need to convert anything. You should just be able to do a string comparison.
I am trying to insert current time to a Time column in the excel using the below code through an oledb connection but when I check the excel the value inserted is in Date format.
Value updated in excel - 1/0/1900 3:54:11 PM
Expected Value - 3:54:11 PM
string currentTime = DateTime.Now.ToString("hh:mm:ss.fff tt");
string cmnd1 = "Create Table [" + currentDate + "] (TestCase char(100), ExecutionTime Time, Result char(20))";
string cmnd2 = "Insert Into [" + currentDate + "] (TestCase, ExecutionTime, Result) values ("+ "'" + tName + "',#dd,'" + result +"')" ;
using (OleDbConnection conn = new OleDbConnection(ConnectionStringtd))
{
OleDbCommand createSheet = new OleDbCommand(cmnd1, conn);
OleDbCommand insertResult = new OleDbCommand(cmnd2, conn);
insertResult.Parameters.AddWithValue("#dd", DateTime.Now.TimeOfDay);
conn.Open();
try
{
createSheet.ExecuteNonQuery();
}
catch(OleDbException) {}
insertResult.ExecuteNonQuery();
}
}
AFAIK, when you enter pure time value stored as a datetime with the entered time portion, and a date part will be January 0, 1900 automatically since the days before 1900 are incorrect in Excel.
Instead of that, pass your DateTime.Now directly to parameter and change your column format type to Time with h:mm:ss tt format in your format cells part. By the way, you just paramterized #dd part. Use parameters for the other values that you try to insert. Don't concatenate them.
insertResult.Parameters.AddWithValue("#dd", DateTime.Now);
And don't use AddWithValue anymore. It may generate unexpected and suprising results sometimes. Use Add method overload to specify your parameter type and it's size.
Also use using statement to dispose your commands as you did for the connection.
I am getting the following error "The conversion of a varchar data type to a datetime data type resulted in an out-of-range value." and the date format is "DD/MM/YY"
public DataSet GetSynchronizeDataForDLDocs(string date_pushed)
{
DataSet ds = new DataSet();
string strQuery=string.Empty;
if (date_pushed != null && date_pushed != string.Empty) // 105
strQuery =
#"select
a.DLNO,
a.NAME,
b.TOPSTRING,
Convert(datetime,a.DOB,103) as DOB,
Convert(datetime,a.DOI,103) as DOI,
Convert(datetime,b.datepushed,103) as datepushed
from
PLInfo_Demo a,
DLInfo_Demo b
where
a.dlno=b.dlno
and
Convert(DateTime,b.datepushed,103) > CONVERT(varchar,'" + date_pushed + #"' ,103)
and
DATEPART(hh, b.datepushed) > Datepart(hh,'" + date_pushed + #"')
and
DATEPART(MI, b.datepushed) > Datepart(MI,'" + date_pushed + #"' )
and
DATEPART(ss, b.datepushed) > Datepart(ss,'" + date_pushed + #"' )
order by b.datepushed desc";
else
strQuery = #"
select
a.DLNO,
a.NAME,
b.TOPSTRING,
Convert(datetime,a.DOB,103) as DOB,
Convert(datetime,a.DOI,103) as DOI,
Convert(datetime,b.datepushed,103) as datepushed
from
PLInfo_Demo a,
DLInfo_Demo b
where
a.dlno=b.dlno ";
ds = DbManager.ExecuteSalarData(
strQuery,
CommandType.Text,
DbManager.strcon2,
null);
return ds;
}
First thing would be do not pass in date_pushed as a string. Parse it in your c# (DateTime.Parse or similar, perhaps specifying a format and culture), and pass it as a parameter. In all the places you have '" + date_pushed + '"', use #theParameter instead.
The next thing is to store b.datepushed as a datetime - there should be no need to use convert on b.datepushed. If it is a string you are doing it wrong.
After that, you are comparing a datetime field to a datetime parameter, which will work without issue. For example:
and Convert(DateTime,b.datepushed,103) > CONVERT(varchar,'" + date_pushed + #"' ,103)
becomes
and b.datepushed > #date_pushed
where b.datepushed is the datetime field, and #date_pushed is the datetime parameter. You can of course use DATEPART etc with a datetime - the important point is: it isn't parsing anything at all.
Some of these must have failed, so please have a look at the actual values:
Convert(datetime,a.DOB,103) as DOB,
Convert(datetime,a.DOI,103) as DOI,
Convert(datetime,b.datepushed,103) as datepushed
I assume you use SQL Server.
The valid datetime range in SQL Server is January 1, 1753 through December 31, 9999, as stated on the datetime (Transact-SQL) MSDN page.
I suggest that you watch all your convert(datetime, ...) statements for values that fall out of this range.