Compare 2 DateTime values in a WHERE clause - sql-server

I have a very simple query. (I'm working in SQL Server 2008.) I'm trying to select all records from a view where their ModifiedOn column is greater than a specified date. The ModifiedOn column is a datetime format. So, I have:
DECLARE #date1 AS datetime = '2013-07-31 24.59.59.999'
SELECT
some_column
FROM dbo.some_view
WHERE ModifiedOn > #date1
SQL is throwing the following error, though:
The conversion of a varchar data type to a datetime data type resulted in an out-of-range value. Why is SQL thinking that one of my dates is a varchar, when I know that both of them are datetime formats? How do I fix it?

Datetime variable expects data to be in format of
YYYY-MM-DD HH:MM:SS.mmm
In your case you are trying to assign a value which is not a valid time. HH.MM.SS.mmm
Secondly a clock never strikes 24:00:00 it goes from 23:59:59.999 to 00:00:00.001.
Also in your case rather than juggling with seconds and milliseconds. just use date value and use the ANSI standard YYYYMMDD which is also sargable.
You could have written your above query something like
SELECT some_column
FROM dbo.some_view
WHERE ModifiedOn >= '20130801'

Related

Date convertion Issue in Ms sql

My table name as tbl_event
Event_ExpiryDate, Event_Date fields data type is varchar, I have using the following query for getting data from the table:
select * from tbl_event
WHERE
LEFT (CONVERT(VARCHAR,Event_ExpiryDate,103),12)>= LEFT(CONVERT(varchar,GetDate(),103),12) and
LEFT (CONVERT(VARCHAR,Event_Date,103),12)<= LEFT(CONVERT(varchar,GetDate(),103),12)
but I am getting a result like this
1 data to be missing. Why? this issue only on some month's date only. Months are 2,4,8,12
The real problem here is your data, and that you're using the wrong data type. Fix the data type, fix the problem.
You can fix that by firstly changing your varchar representation of a date to an unambiguous Date format, yyyyMMdd (This assumes your dates are in the format dd/MM/yyyy):
UPDATE dbo.tbl_event
SET Event_Date = CONVERT(varchar(8),CONVERT(date,Event_Date,103),112),
Created_Date = CONVERT(varchar(8),CONVERT(date,Created_Date,103),112),
Event_ExpiryDate = CONVERT(varchar(8),CONVERT(date,Event_ExpiryDate,103),112);
Then you can ALTER the table to fix your data types:
ALTER TABLE dbo.tbl_event ALTER COLUMN Event_Date date NULL; --Use NOT NULL if not NULLable
ALTER TABLE dbo.tbl_event ALTER COLUMN Created_Date date NULL; --Use NOT NULL if not NULLable
ALTER TABLE dbo.tbl_event ALTER COLUMN Event_ExpiryDate date NULL; --Use NOT NULL if not NULLable
Note: If any of your dates have bad values, for example '31/04/2019', the above will fail. You can get around this by changing the CONVERT functions to TRY_CONVERT, however any values that fail to convert will have the value NULL. If your columns have the NOT NULL property you will need to ensure you handle that too. If you do have bad values in your table, I strongly suggest taking a backup, or copy of the database/table first, so that you have a historical copy. (Of course, does a date like '31/04/2019' or '12/13/2018' have any meaning anyway?)
You can use only convert() :
where convert(date, Event_ExpiryDate, 103) >= convert(date, getdate()) and
convert(date, Event_Date, 103) <= convert(date, getdate());
However, storing varchar date is really bad idea. It will lead you lots of in trouble.

SQL Server - Select between 2 dates of type DD/MM/YYYY

I want to query a datetime field using a range of dates provided in the format DD/MM/YYYY.
I know that to convert datetime to a DD/MM/YYYY format that I can use:
CONVERT(CARCHAR(10), ORDERDATE,103)`
And this works fine when querying a single date, eg:
SELECT DISTINCT
CONVERT(DATE, ORDERDATE),
CONVERT(CARCHAR(10), ORDERDATE,103)
FROM ORDERS
WHERE CONVERT(CARCHAR(10), ORDERDATE,103) = '19/10/2017'
Returns: 2017-10-19, 19/10/2017
However it does not work on a range of dates, eg:
WHERE CONVERT(CARCHAR(10), ORDERDATE,103) BETWEEN '17/10/2017' AND '19/10/2017'
Returns:
2014-02-05
2016-12-12
2013-04-30
I know there are hundreds of threads about SQL dates, but they all seem to be regarding reformatting the output and not preparing the input. Do I need to reformat my DD/MM/YYYY inputs?
To query a range of dates, use the DATE-datatype instead of VARCHAR.
If datatype of column ORDERDATE is DATETIME:
WHERE CONVERT(DATE, ORDERDATE) BETWEEN
CONVERT(DATE, '17/10/2017', 103) AND CONVERT(DATE, '19/10/2017', 103)
The conversion of ORDERDATE is only necessary if the start and end date are the same. (in this case, when no conversion is done, only dates with a time value of '00:00:00.000' will be returned)
EDIT:
To omit the conversion of ORDERDATE you can add the time to the dates and convert them to DATETIME instead of DATE, like this:
WHERE ORDERDATE BETWEEN
CONVERT(DATETIME, '19/10/2017 00:00:00') AND CONVERT(DATETIME, '19/10/2017 23:59:59.999');
Or even simpler, like suggested in #Used_By_Already's answer:
WHERE ORDERDATE >= '20171017' AND ORDERDATE < '20171020' --Note the end date is here +1 day
SQL Server date information should NOT be stored "in a format". If if they are literally stored in that format then they are NOT dates as far as the database is concerned (they are "strings" that look like dates) and you will have a nightmare to deal with if they are DD/MM/YYYY because they simply will not behave like dates should.
There are several specific data types in SQL Server for date/time information (datetime, datetime2, smalldatetime, date, time) but ALL of these do not store data in a human readable format at all. Instead they stored as groups of numbers, which will be displayed in a human readable manner, and in your case - by default - you are seeing then in DD/MM/YYYY format. A user in China might prefer to see a date in YYYY.MM.DD or in the USA as MM/DD/YYYY. This is possible because a human format is applied on top of the numbers that are stored before they get displayed.
So. In SQL Server there is a "safe" date literal in the form of 'YYYYMMDD' and this may be used without the need to CONVERT or CAST:
IF your [ORDERDATE] column is a date (or smalldatetime/datetime/datetime2) then this will work:
WHERE ORDERDATE BETWEEN '20171017' AND '20171019'
OR, you may explicitly convert a string to but you need a "style number" to be present to make these fully reliable. Style 103 for example is for DD/MM/YYYY
WHERE ORDERDATE BETWEEN CONVERT(date, '17/10/2017',103) AND CONVERT(date, '19/10/2017',103)
Although "between" has been used in the discussion above a far more reliable method of forming date ranges is to NOT use "between", instead do it this way:
WHERE ORDERDATE >= '20171017' AND ORDERDATE < '20171020'
With this pattern (note the second day is now +1) it does not matter which date precision is stored in the column. For example, see Bad habits to kick : mis-handling date / range queries

Comparing dates with current date in Sql server

I have a table which has list of some events with dates. I am trying to write a stored procedure that will return only the upcoming events.
I have written the following query in the stored procedure:
SELECT *
FROM Events
WHERE tDate >= (select CAST(GETDATE() as DATE))
But this is not returning correct result. This is also showing results that have dates less than current date. How to write a query that will return all the events that have date equal or greater than today's date.
Edit: Dates that have been entered on the table have the format yyyy/dd/mm and getdate() returns date in the format yyyy/mm/dd. I think this is causing the problem. Dates that have been entered into the table has been taken using jquery date picker. Any solution to this problem?
Not sure why you have an additional select
SELECT *
FROM Events
WHERE tDate >= CAST(GETDATE() as DATE)
your DATE data is incorrectly stored within Sql Server. When your application passes the string '2015-09-04' and you save that your date column, it is saved as 4th Sept 2015 and not 9th April 2015. Hence your query returns such rows as they are greater than GETDATE().
Example
DECLARE #D VARCHAR(10) = '2015-09-04'
SELECT CONVERT(VARCHAR(20),CONVERT(DATE,#D),109)
you need to fix your data and then use a CONVERT with style when saving dates in your table from application, using something like this. CONVERT(DATE, '20150409',112)
DECLARE #D VARCHAR(10) = '20150409'
SELECT CONVERT(VARCHAR(20),CONVERT(DATE,#D,112),109)
Refer these threads for more info:
Impossible to store certain datetime formats in SQL Server
Cast and Convert

Select condition on date for datetime field

I want to impose date condition on a date time field in SQL Server.
The datetime field is like this 2011-01-19 17:57:18.350 and when I execute below query it yields no results.
select top 1000 *
from [dbo].[RouteState]
where convert (date, logtime, 101) = '12-01-2015'
Can someone help me what's going wrong here?
There is no need to convert the datetime column to anything. Use a closed-open interval instead and change the format of your string literal to yyyymmmdd to make sure that SQL Server will interpret the date value in the same way regardless of regional and date format settings.
select top 1000 *
from [dbo].[RouteState]
where logtime >= '20150112' and
logtime < '20150113';
For more info on casting a column to date you can have a look at Cast to date is sargable but is it a good idea?

SQL Server / TSQL cast smalldatetime using isnull

I'm trying to just do a simple check against a column in the table:
If (endDate is null)
use smalldatetime '12/31/2200'
else
use endDate from column
Here is my stored procedure:
ALTER PROCEDURE [dbo].[getCostByDate] #date smalldatetime, #productID int
AS
SELECT cost
FROM testDB.dbo.product_cost
WHERE #date between startDate and isNull(endDate,cast('12/31/2200' as smalldatetime)) and product_id = #productID
I tried to 'cast' the '12/31/2200' to format it for a smalldatetime, but I'm getting the error:
"The conversion of a varchar data type to a smalldatetime data type resulted in an out-of-range value."
The problem is that the date range for smalldatetime is 1900-01-01 through 2079-06-06 and your value is past the upper bound. The solution is to use a value inside the range, or another date type like datetime or datetime2.
cast('12/31/2078' as smalldatetime) would work for instance.
Here's the key:
and isNull(endDate,cast('2029-04-25T15:50:59.997' as smalldatetime))
You have to give the whole date even though it's a smalldatetime... Also, you can't use 2200, it's too far in the future I guess...

Resources