比较存储为varchar

时间:2015-05-31 16:48:59

标签: sql-server date datetime

我需要将存储在我的数据库中的日期作为varchar与今天的日期进行比较。

具体来说,我需要排除任何已经过了日期的记录。

我试过了:

SELECT * FROM tblServiceUsersSchedule 
WHERE ScheduleEndDate !='' AND ScheduleEndDate < '2015/05/31'

此选定值,例如17/06 / 2012 和19/04/2015,两者都已通过,以及2015年6月1日尚未完成。

然后我尝试使用以下方式转换数据:

SELECT * 
FROM   tblServiceUsersSchedule 
WHERE  CAST(ScheduleEndDate as DATETIME)  < CAST('05/31/2015' as DATETIME) AND ScheduleEndDate !='' AND ScheduleEndDate is not null

但是出现了以下错误:

  

导致将varchar数据类型转换为日期时间数据类型   在超出范围的价值。

我检查了后面的数据,没有一个是null,没有空白空格。所有日期都是dd / mm / yyyy格式。

我无法弄清楚如何比较存储在今天日期的varchar日期。

3 个答案:

答案 0 :(得分:3)

将日期值存储为varchar是完全错误的。

如果可能,您应该更改表格以将它们存储为日期数据类型 您只需几个简单的步骤即可完成:

  1. 将当前列(我猜测ScheduleStartDate也是varchar)重命名为columnName_old。使用sp_rename

  2. 可以轻松完成此操作
  3. 使用alter table添加具有相应数据类型的列。

  4. 使用update语句将旧列中的值复制到新列。由于所有日期都以相同的格式存储,因此您可以使用set ScheduleStartDate = convert(date, NULLIF(ltrim(rtrim(ScheduleStartDate_old)), ''), 103),如下所示:script index as如果您的sql server版本是2012或更高版本,请使用convert。请注意,我已使用try_convertnullifltrim将仅包含空格的值转换为null。
  5. 删除并重新创建引用这些列的索引。最简单的方法是右键单击SSMS上的索引,然后选择drop and create - &gt; alter table
  6. 使用SELECT * FROM tblServiceUsersSchedule WHERE CONVERT(DATE, NULLIF(ScheduleEndDate, RTRIM(LTRIM('')), 103) < CAST(GETDATE() As Date); AND ScheduleEndDate IS NOT NULL 删除旧列。
  7. 注意:如果在数据库的任何其他对象中引用这些列,您也必须更改这些对象。这包括存储过程,外键等。“

    如果您无法更改列的数据类型,并且您的sql server版本低于2012,则需要使用如下转换:

    Try_convert

    请注意,如果您的列的数据不是dd / MM / yyyy格式的单行,则会引发错误。

    对于sql server版本2012或更高版本,请使用SELECT * FROM tblServiceUsersSchedule WHERE TRY_CONVERT(DATE, NULLIF(ScheduleEndDate, RTRIM(LTRIM('')), 103) < CAST(GETDATE() As Date); AND ScheduleEndDate IS NOT NULL 。如果转换失败,此函数将返回null:

    CAST(GETDATE() as Date)

    注意:我已使用ScheduleEndDate删除当前日期的时间部分。这意味着您只能获得ScheduleEndDate至少有一天的记录。如果您还要获取今天<=所在的记录,请使用<代替<nav class = "navbar navbar-inverse"> <div class = "navbar-header"> <button type = "button" class = "navbar-toggle" data-toggle = "collapse" data-target = "#mynav"> <span class = "icon-bar"></span> <span class = "icon-bar"></span> <span class = "icon-bar"></span> </button> <a href = "#" class = "navbar-brand">Stack Ask</a> </div> <div class = "collapse navbar-collapse" id = "mynav"> <ul class = "nav navbar-nav"> <li class = "active"><a href = "#">Home</a></li> <li><a href = "#">Education</a></li> <li class = "dropdown"><a class = "dropdown-toggle" data-toggle = "dropdown" href = "#">Tutorials <span class = "caret"></span> </a> <div class = "dropdown-menu"> <ul class = "nav navbar-nav"> <li><a href = "#">Programming Languages</a></li> <li><a href = "#">Web Development</a></li> </ul> </div> </li> <li><a href = "#">Kingdom Centre</a></li> <li><a href = "">About</a></li> </ul> <ul class = "nav navbar-nav navbar-right"> <li class = "dropdown"><a href = "#" class = "dropdown-toggle" data-toggle = "dropdown"><span class = "glyphicon glyphicon-search"></span> Search</a> <div class = "dropdown-menu"> <ul class = "nav navbar-nav"> <li> <form class="form-search"> <div class = "container-fluid"> <input type="text" class="form-control input-medium search-query" style = "border-radius: 25px;" /> <button type="submit" class="btn" style = "margin-top: 10px; margin-left: 5px;">Search</button> </div> </form> </li> </ul> </div> </li> <li><a href = "#"><span class = "glyphicon glyphicon-user"></span> Sign Up</a></li> <li><a href = "#"><span class = "glyphicon glyphicon-log-in"></span></span> Log In</a></li> </ul> </div> </nav>

    最后一件事:在where子句中使用列上的函数将阻止Sql Server对这些列使用任何索引。
    这是您应该将列更改为适当数据类型的另一个原因。

答案 1 :(得分:0)

除了人们已经建议您永远不应将DATETIME存储为VARCHAR之外。始终将其存储在DATETIME类型列中;我认为你应该在WHERE

中改变你的状况
ScheduleEndDate < '2015/05/31'

为了获得尚未过去的所有日期

ScheduleEndDate >= '2015/05/31'

您的查询应该是

SELECT * FROM tblServiceUsersSchedule 
WHERE ScheduleEndDate IS NOT NULL
AND ScheduleEndDate >= '2015/05/31'

答案 2 :(得分:0)

如果您必须将日期存储为varchar(以及其他答案,这是一个差的做法),那么使用yyyy-mm-dd之类的ISO样式格式应该可以进行文本比较,而不会出现问题。 如果您的列是日期数据类型,并且您使用的是SQL 2012或更高版本,请使用DATEFROMPARTS(或其变体之一)进行日期比较,所以

WHERE DateToCompare < DATEFROMPARTS (2019, 12, 31)

而不是

WHERE DateToCompare < '2019-12-31'

SQL处理后一种很好,但是前一种更“正确”。