SQL - 日期查询问题 - varchar 到日期时间的转换导致值超出范围

标签 sql tsql datetime sql-server-2008-r2

我有一个不再在这里的同事编写的 SQL 查询。该查询作为 SSIS 作业的一部分运行,并且从本月开始失败并出现以下错误:

The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.



查询本身只是一个带有 where 子句的基本选择,用于查找特定时间范围内的值(日期范围介于 @startdate@enddate 之间)

确定时间范围的代码如下:
DECLARE     @RunDateTime datetime
DECLARE     @RunDate datetime
DECLARE     @StartDate datetime
DECLARE     @EndDate datetime
DECLARE     @Month int
DECLARE     @Year int
DECLARE     @strStartDate varchar(10)

SET     @RunDateTime = GetDate()
SET     @RunDate = cast(round(convert(real, @RunDateTime),0,1) as datetime)

IF                  DATEPART(d, @RunDate) = 16
    BEGIN       
                    SET @StartDate =  DATEADD(d, -15, @RunDate)
                    SET @EndDate = @RunDate
    END
ELSE
    BEGIN
                    IF      Month(@RunDate) = 1
                            SET @Month = 12
                    ELSE    
                            SET @Month = Month(@RunDate) - 1

                    IF      Month(@RunDate) = 1
                            SET @Year = Year(@RunDate) - 1
                    ELSE
                            SET @Year = Year(@RunDate)

                    SET @strStartDate = CONVERT(varchar(2), @Month)+ '/16/' + CONVERT(varchar(4), @Year)
                    SET @StartDate = CONVERT(datetime, @strStartDate, 101)
                    SET @EndDate = @RunDate
    END

这项工作每月运行两次。 1月1日至15日数据16日一次,16日至上月末数据次月1日1次。

从我在网上能找到的,使用varcharstrStartDate可能是罪魁祸首吗?我对 SQL 不够熟悉,不知道如何替换那里发生的所有转换内容?另外,是否有比仅获取运行时间更好的方法来确定月末日期?任何帮助都将不胜感激。

(PS,我们在 SQL Server 2008 R2 上运行此作业)我与 DBA 进行了核实,他说 SQL Server 上的本地化或区域设置没有发生任何变化。

最佳答案

SQL Server 支持多种格式 - 请参阅 MSDN Books Online on CAST and CONVERT .大多数这些格式是 受抚养人 关于您拥有的设置 - 因此,这些设置有时可能会起作用 - 有时则不起作用。

解决这个问题的方法是使用(稍微改编) ISO-8601 日期格式 SQL Server 支持的 - 此格式有效 总是 - 无论您的 SQL Server 语言和日期格式设置如何。

ISO-8601 format SQL Server 支持的有两种类型:

  • YYYYMMDD仅用于日期(无时间部分);请注意:没有破折号! ,这很重要! YYYY-MM-DD不是 独立于 SQL Server 中的日期格式设置,并且将 不是 在所有情况下工作!

  • 或者:
  • YYYY-MM-DDTHH:MM:SS对于日期和时间 - 请注意:此格式有破折号(但可以省略)和固定的 T作为 DATETIME 的日期和时间部分之间的分隔符.

  • 这对 SQL Server 2000 和更新版本有效。

    如果您使用 SQL Server 2008 或更新版本和 DATE数据类型(仅 DATE - 不是 DATETIME !),那么您确实也可以使用 YYYY-MM-DD格式,这也适用于 SQL Server 中的任何设置。

    另外:对于 SQL Server 2008,建议使用 DATETIME2 (而不是 DATETIME )如果可能的话。 DATETIME2字符串解析对错误和/或不同格式(如美国 AM/PM 格式等)的容忍度要高得多。

    不要问我为什么整个主题如此棘手且有些令人困惑 - 这就是它的方式。但随着 YYYYMMDD格式,您应该适用于任何版本的 SQL Server 以及 SQL Server 中的任何语言和日期格式设置。

    关于SQL - 日期查询问题 - varchar 到日期时间的转换导致值超出范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14124584/

    相关文章:

    SQL Server 算术溢出错误将 IDENTITY 转换为数据类型 int 但尚未达到 int 的最大值

    c# - SQL Order 结果有点按字母顺序 Entity Framework/C#

    sql - T-SQL,计划作业中的多个更新

    返回每个 ID 的最新记录的 SQL 查询

    c# - 脚本任务填充 : SelectCommand. 连接属性尚未初始化

    c# - 使非空类可为空

    c# - 无法使用 C# 客户端反序列化日期时间属性 Neo4j

    mysql - SQL双数据库安全

    java - 将具有自定义时区的 java.util.Date 转换为 UTC

    SQL:如何计算可能重叠的日期范围之间的唯一天数?