SQL BETWEEN是否适用于字符串日期?

时间:2013-12-05 22:43:12

标签: sql-server string datetime between

我有一个大型SQL,必须生成一些日期才能使用,并与DATETIME列进行比较,我也将其转换为字符串,以便将字符串与字符串进行比较。但BETWEEN是否可以使用字符串?

...
    AND ((pur.StudyYearID <= @StudyYear
        AND CONVERT(varchar, pur.StartDate, 112) BETWEEN CONVERT(varchar, GETDATE(), 112)
                                                     AND CONVERT(varchar, CAST(CAST(YEAR(DATEADD(YEAR, 1, GETDATE())) AS varchar) + '1231' AS DATETIME), 112))
         OR (pur.StudyYearID > @StudyYear
        AND CONVERT(varchar, pur.StartDate, 112) BETWEEN STR(YEAR(GETDATE()) + SUBSTRING(pur.StudyYearID, 2, 1) - SUBSTRING(@Workgroup, 1, 1)) + '0101' 
                                                     AND STR(YEAR(GETDATE()) + SUBSTRING(pur.StudyYearID, 2, 1) - SUBSTRING(@Workgroup, 1, 1)) + '1231'))
    ...

我无法指出它,但我“认为”这是有效的。但是,我对BETWEEN很怀疑。 BETWEEN是否仅适用于DATETIME数据类型等实际日期,还是可以像我上面使用Strings一样工作?如果没有,我认为我必须删除BETWEEN并用dreaded&gt; =和&lt; =替换它,对吗?

顺便说一下上面的每个日期字符串计算都有效,因为我已经单独测试了它们,并且我确实得到了YYYYMMDD格式的日期。

由于

更新 上述要点是避免在比较字符串时使用&gt; =和&lt; =。我想使用BETWEEN,但将DATE作为字符串,因为我想确保我将“苹果与苹果”进行比较。然而,这是“糟糕的编程”,因为我可以简单地使用CAST()来剥离时间并使用BETWEEN,如下所述。

@StudyYearID可以是[S1,S2,S3或S4]的任何内容 @WorkGroup可以是'1A,1B,1C,1D,1E到4E'

的任何内容

对不起有困惑

3 个答案:

答案 0 :(得分:2)

为什么要尝试将日期比作字符串?日期应该是DATETIME对象。目前还不清楚你在使用StudyYearID或@Workgroup做什么,但是如果日期的一部分需要以其他方式构建,那么在进行BETWEEN比较之前将其转换为DATETIME对象。

如果没有其他方法来提出你的“介于”值之外的其他值,而不是先将它们构建为字符串,那么至少在比较之前进行投射,如下所示:

    AND (pur.StartDate BETWEEN GETDATE()
                AND CAST(CAST(YEAR(DATEADD(YEAR, 1, GETDATE())) AS varchar) + '-12-31' AS DATETIME))

......与您的其他值相同。

答案 1 :(得分:1)

哦,天哪,这里有很多事情都出错了。

  1. 将所有这些日期/日期时间值转换为字符串。不要这样做。日期和日期时间值是日期和日期时间值 - 将它们转换为字符串会导致各种不好的事情,例如缺乏验证,无法使用索引进行搜索或范围扫描,丢弃各种内置日期函数支持等等。 / p>

  2. Converting to varchar without length. This is a bad habit and should be avoided so you aren't a victim to silent truncation

  3. Using BETWEEN for date range queries. You should only do this if the underlying column is DATE, and even then I'd be careful. In order to properly use underlying indexes (that exist today, or that may exist tomorrow), you should use an open-ended date range

  4. 我认为通过避免对字符串的所有转换,这个查询更加整洁,并且如果StartDate(今天或将来)上存在索引,也会为索引使用提供更好的搜索。

      AND 
      (
        (
          pur.StudyYearID <= @StudyYear
          AND pur.StartDate >= @d AND 
          AND pur.StartDate < DATEADD(YEAR, 1, @next_year)
        )
        OR 
        (
          pur.StudyYearID > @StudyYear
          AND pur.StartDate >= DATEADD(YEAR, YEAR(GETDATE()) 
              + SUBSTRING(pur.StudyYearID, 2, 1) - LEFT(@WorkGroup, 1) - 1900, 0)
          AND pur.StartDate < DATEADD(YEAR, 1 + YEAR(GETDATE()) 
              + SUBSTRING(pur.StudyYearID, 2, 1) - LEFT(@WorkGroup, 1) - 1900, 0)
        )
      )
    

答案 2 :(得分:0)

是的,转换为ISO 8601格式的字符串的日期将使用SQL Server附带的任何排序规则设置按时间顺序排序。每个人都会问你的问题是,“为什么世界上你在将日期转换为字符串之前将它们相互比较?”​​