I need to compare dates that are stored in my database as varchar against today\'s date.
Specifically, I need to exclude any records with a date that has passed.
Other than what people have already suggested that you should never store DATETIME
as VARCHAR
. Always store it in a DATETIME
type column; I think you should change your condition in WHERE
ScheduleEndDate < '2015/05/31'
To this, in order to get all dates which hasn't passed yet
ScheduleEndDate >= '2015/05/31'
Your query should look like
SELECT * FROM tblServiceUsersSchedule
WHERE ScheduleEndDate IS NOT NULL
AND ScheduleEndDate >= '2015/05/31'
If you HAVE TO store your dates as varchar (and as per other other answers, this is a poor practice), then using an ISO style format like yyyy-mm-dd should allow textual comparisons without issue. If your column is a date data type, and you're using SQL 2012 or later then use DATEFROMPARTS (or one of its variants) for date comparison, so
WHERE DateToCompare < DATEFROMPARTS (2019, 12, 31)
rather than
WHERE DateToCompare < '2019-12-31'
SQL handles the latter fine, but the former is more "correct".
Storing date values as varchar is simply wrong.
If possible, you should alter the table to store them as date data type.
You can do it in a few simple steps:
Rename the current columns (I'm guessing ScheduleStartDate is also varchar) to columnName_old. This can be easily done by using sp_rename.
Use alter table to add the columns with the appropriate data type.
set ScheduleStartDate = convert(date, NULLIF(ltrim(rtrim(ScheduleStartDate_old)), ''), 103)
If your sql server version is 2012 or higher, use try_convert. Note i've used the nullif, ltrim and rtrim to convert values that only contains white spaces to null.script index as
-> drop and create
.alter table
to remove the old columns.Note: if these columns are being referenced in any other objects on the database you will have to change these objects as well. This includes stored procedures, foreign keys etc`.
If you can't change the data types of the columns, and your sql server version is lower then 2012, you need to use convert like this:
SELECT * FROM tblServiceUsersSchedule
WHERE CONVERT(DATE, NULLIF(ScheduleEndDate, RTRIM(LTRIM('')), 103)
< CAST(GETDATE() As Date);
AND ScheduleEndDate IS NOT NULL
Note that if you have even a single row where the column's data is not in dd/MM/yyyy format this will raise an error.
For sql server versions 2012 or higher, use Try_convert
. This function will simply return null if the conversion fails:
SELECT * FROM tblServiceUsersSchedule
WHERE TRY_CONVERT(DATE, NULLIF(ScheduleEndDate, RTRIM(LTRIM('')), 103)
< CAST(GETDATE() As Date);
AND ScheduleEndDate IS NOT NULL
Note: I've used CAST(GETDATE() as Date)
to remove the time part of the current date. This means that you will only get records where the ScheduleEndDate
is at least one day old. If you want to also get the records where the ScheduleEndDate
is today, use <=
instead of <
.
One final thing: Using functions on columns in the where clause will prevent Sql Server to use any indexing on these columns.
This is yet another reason why you should change your columns to the appropriate data type.