Comparing dates stored as varchar

后端 未结 3 1966
栀梦
栀梦 2020-12-02 01:44

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.

相关标签:
3条回答
  • 2020-12-02 02:01

    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'
    
    0 讨论(0)
  • 2020-12-02 02:03

    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".

    0 讨论(0)
  • 2020-12-02 02:13

    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:

    1. Rename the current columns (I'm guessing ScheduleStartDate is also varchar) to columnName_old. This can be easily done by using sp_rename.

    2. Use alter table to add the columns with the appropriate data type.

    3. 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, use try_convert. Note i've used the nullif, ltrim and rtrim to convert values that only contains white spaces to null.
    4. 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.
    5. 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.

    0 讨论(0)
提交回复
热议问题