Comparing dates stored as varchar
Solution 1:
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.- Copy the values from the old columns to the new columns using an update statement. Since all of the dates are stored in the same format, you can use
convert
like this:set ScheduleStartDate = convert(date, NULLIF(ltrim(rtrim(ScheduleStartDate_old)), ''), 103)
If your sql server version is 2012 or higher, usetry_convert
. Note i've used thenullif
,ltrim
andrtrim
to convert values that only contains white spaces to null. - Drop and recreate indexes that is referencing these columns. The simplest way to do this is by right-clicking the index on SSMS and choose
script index as
->drop and create
. - Use
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.