Finding Records Between 2 Times - c#

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.

Related

date in sql query with asp.net program

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.

Azure Document DB Stored procedure DateTime query

I am using Document DB stored procedure to retrieve telemetry time based data into my C# web application. I am having 1000 of documents in my collection. I want to do calculations based on Date Time object. I want to get all documents based on time interval. Using SQL query i am getting result of last 24 hrs records.
SqlQuerySpec query = new SqlQuerySpec("SELECT * FROM c where (c.logdatetime between '" + DateTime.Now.AddDays(-1).ToString("yyyy-MM-ddTHH:mm:ssZ") + "' and '" + DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ssZ") + "')");
I want to write same query using Stored Procedure. How to do it in Stored Procedure. Thanks in advance.
First of all: I would advise you against performing your queries against a formatted DateTime string. Store the values as "ticks" (seconds or milliseconds since epoch, also known as Unix Time).
Current time in ticks:
// C#
DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
// JavaScript
new Date().value
If you want to go back 24hrs, just substract the equivalent ticks from the time. 24 * 60 * 60 * 1000
Second of all: At the very least get rid of the timezones. Your implementation seems to be highly reliable on having only one timezone. Ever. Your writing clients and the CosmosDB server would need to run in the same timezone, guaranteed. Please use DateTime.UtcNow instead of DateTime.Now. Or DateTimeOffset.
(If you are not manually calling ToString before writing your data to CosmosDB, it will already have been stipped of the timezone, see Creating and comparing dates inside CosmosDB stored procedures)
// C#
DateTimeOffset.UtcNow.ToString("s");
// JavaScript
new Date().toISOString();
This is a sample stored procedure:
https://github.com/Azure/azure-documentdb-js-server/blob/master/samples/stored-procedures/SimpleScript.js
function simple(prefix) {
var collection = getContext().getCollection();
var isAccepted = collection.queryDocuments(
collection.getSelfLink(),
'SELECT * FROM root r',
function (err, feed, options) {
...
});
}
It feels like you are trying to ask how to translate your code into JavaScript.
SqlQuerySpec query = new SqlQuerySpec("SELECT * FROM c where
(c.logdatetime between '" + DateTime.Now.AddDays(-1)
.ToString("yyyy-MM-ddTHH:mm:ssZ") + "' and '" + DateTime.Now
.ToString("yyyy-MM-ddTHH:mm:ssZ") + "')");
Which would be something like this using ticks:
var now = new Date().value;
var yesterday = now - 24 * 60 * 60 * 1000;
var query = "SELECT * FROM c where (c.logdatetime between '" + yesterday + "' and '" + now + "')"
If you need to keep the strings:
var now = new Date();
var yesterday = new Date(now.value - 24 * 60 * 60 * 1000);
var query = "SELECT * FROM c where (c.logdatetime between '" + yesterday.toISOString() + "' and '" + now.toISOString() + "')"
Not sure how perfect this behaves when daylight savings time comes into play, but you should find plenty of resources for that if that is critical for you.

Comparing a month and year sql database

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.

Conversion failed when converting date and/or time from character string

I am trying to query the database where date is between today and yesterday but am getting error saying Conversion failed when converting date and/or time from character string.
My query is below with my parameters today and yesterday
string today = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day).ToString("yyyy-MM-dd");
string yesterday= new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day-1).ToString("yyyy-MM-dd");
string errorsPerHourQuery = "WITH data_CTE(ErrorDay)" +
"AS(" +
"SELECT DATEPART(hh, Date) AS ErrorDay FROM cloud.ErrorLog " +
"WHERE Date BETWEEN '#yesterday' AND '#today' " +
"AND CAST(Message AS varchar(200)) ='#message'"+
")" +
"SELECT ErrorDay, COUNT(*) AS count FROM data_CTE GROUP BY ErrorDay ORDER BY ErrorDay";
conn.Open();
cmd.Parameters.AddWithValue("#message", message);
cmd.Parameters.AddWithValue("#yesterday", yesterday);
cmd.Parameters.AddWithValue("#today", today);
cmd.CommandType = CommandType.Text;
You must remove simple cote ' from parmeters in query :
..BETWEEN #yesterday AND #today
You don't need to create today and yesterday with specific format, you can simply get variable like :
var today = DateTime.Today;
var yesterday = DateTime.Today.AddDays(-1);
and use Parameter with SqlDbType.DateTime and then pass the DateTime directly to the parameter (do not need to convert).
cmd.Parameters.Add("#yesterday", SqlDbType.DateTime).Value = yesterday
cmd.Parameters.Add("#today", SqlDbType.DateTime).Value = today
First off, you're calculating your today and yesterday wrong. Here's the correct way:
var today = DateTime.Today;
var yesterday = today.AddDays(-1);
And regaring query: remove ticks (') from around your named parameters so that your query reads ...BETWEEN #yesterday and #today... and you'll be all set.
Problem is that you are quoting your command parameters which is getting considered as string literal instead of parameter as seen below.
WHERE Date BETWEEN '#yesterday' AND '#today'
You should change it to
WHERE [Date] BETWEEN #yesterday AND #today
There are lots of good points in the other answers especially. #Abdellah does a good job of teaching the datetime datatype and the appropriate value, but your SQL query itself needs work and may be why you are not getting what you want. Because just like the #yesterday and #today you need to remove the ''(ticks) from #message. Then you can do your query in 1 step you don't need the cte. Plus if you aren't going to pass any dates other than yesterday or today there is no need for parameters use SQL's built in functions.
So remove all of the ticks around all of your parameters (#yest...)
Here is a SQL query that should work for you:
SELECT
ErrorHour = DATEPART(HH,[Date])
,[Count] = COUNT(*)
FROM
cloud.ErrorLog
WHERE
--use this line from midnight yesterday to midnight today
CAST([Date] AS DATE) BETWEEN CAST(GETDATE() - 1) AND CAST(GETDATE())
--what is the datatype for message does it really need to be cast?
AND CAST([Message] AS VARCHAR(200)) = #Message
GROUP BY
DATEPART(HH,[Date])
ORDER BY
ErrorHour
Note I put ErrorHour you are welcome to change to ErrorDay, but you are counting errors per hours not days, to change what you are counting simply change your DATEPART() to be the time component you want, e.g. minutes, etc..
Next Do you really need to cast Message field?
On the dates. Are you wanting everything today and yesterday or really just yesterday? If just yesterday swap this line into the query for the other date line:
--if you really just want yesterday midnight to 11:59:59 PM the it should be
CAST([Date] AS DATE) = CAST(GETDATE()-1 AS DATE)
Next if you really really want to pass yesterday and today as parameters and you want all of yesterday and all of today do the following and update your parameter definitions in your code as the other posts suggest.
--use this line from midnight yesterday to midnight today
CAST([Date] AS DATE) BETWEEN CAST(#yesterday AS DATE) AND CAST(#Today AS DATE)

Oracle - not a valid month

I get a timestamp from Facebook in the below code
cust_updated_time = obj["updated_time"].ToString();//2013-08-01T02:55:31+0000
abccusttime = cust_updated_time.Substring(0, cust_updated_time.ToString().Length - 3);//2013-08-01T02:55:31+0
Here I'm trying to insert into Oracle table
to_date('" + abccusttime + "', 'mm-dd-yyyy hh24:mi:ss')
but I get an error "not a valid month"
Any ideas? Thanks in advance.
if this is your date:
2013-08-01T02:55:31+0
It should look like this:
2013-08-01 02:55:31
Than you can use TO_DATE function (with correct mask format):
to_date('" + abccusttime + "', 'yyyy-mm-dd hh24:mi:ss')
When you try to map:
2013-08-01T02:55:31+0
with the format:
mm-dd-yyyy hh24:mi:ss
it's not going to work simply because your date components are in the wrong place. It's expecting a two-digit month at the start but you're giving it the century of 20, which is most definitely not a valid month.
You need to either change your data or your mapping so that they match.
It's probably easier to parameterize your query, but in this case you've got your time format wrong. To match;
2013-08-01T02:55:31+0000
you need a format like;
yyyy-MM-dd"T"hh24:mi:ss"+0000"
or, if you want the preprocessed format with a single zero;
yyyy-MM-dd"T"hh24:mi:ss"+0"
Sample;
SELECT TO_DATE('2013-08-01T02:55:31+0000', 'yyyy-MM-dd"T"hh24:mi:ss"+0000"') FROM DUAL;
> August, 01 2013 02:55:31+0000
Oracle date format reference.
You could also match/process the time zone information, but since it's not clear what result you'd like if it were set, I left it out (TZH and TZM will help there)
A rather trivial SQLfiddle.
The Oracle date format you want is mm-dd-yyyy, but the facebook timestamp is yyyy-mm-dd.
You should do something like this instead;
to_date(:abccusttime, 'mm-dd-yyyy hh24:mi:ss')
Then set a parameter for abbcusttime, also don't use apostrophes (') when adding parameters, it doesn't like that :)
OracleCommand.Parameters.Add(":abccusttime", OracleDbType.Varchar2).Value = abccusttime;
You better use parameters
DateTime updatedtime = obj["updated_time"] as DateTime;
var statement = "..... where Updated_time > :updatedtime";
using (OracleConnection connection = new OracleConnection(connectionString))
using (OracleCommand command = new OracleCommand(statement, connection))
{
command.Parameters.AddWithValue(":updatedtime", updatedtime );
command.Connection.Open();
command.ExecuteNonQuery();
}

Categories