6

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

将 varchar 数据类型转换为 datetime 数据类型导致值超出范围。

查询本身只是一个带有 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日至15日的数据为16日一次,16日至上月末的数据为下个月1日的数据。

我对 SQL 不够熟悉,不知道如何替换那里发生的所有转换内容?此外,有没有比仅获取运行时间更好的方法来确定月末日期?任何帮助都将不胜感激。varcharstrStartDate

(PS,我们在 SQL Server 2008 R2 上运行此作业)我与 DBA 进行了核对,他没有说 SQL 服务器上的本地化或区域设置已更改。

4

1 回答 1

4

SQL Server 支持多种格式 - 请参阅有关 CAST 和 CONVERT 的 MSDN 联机丛书。这些格式中的大多数取决于您拥有的设置 - 因此,这些设置有时可能有效 - 有时无效。

解决此问题的方法是使用 SQL Server 支持的(稍作调整的)ISO-8601 日期格式- 这种格式始终有效- 无论您的 SQL Server 语言和日期格式设置如何。

SQL Server 支持的ISO-8601 格式有两种形式:

  • 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(而不是)。对于错误和/或不同的格式(如美国 AM/PM 格式等),字符串的解析要宽容得多。DATETIMEDATETIME2

不要问我为什么整个话题如此棘手和令人困惑——事情就是这样。但是使用该YYYYMMDD格式,您应该适用于任何版本的 SQL Server 以及 SQL Server 中的任何语言和日期格式设置。

于 2013-01-02T15:39:23.760 回答