处理varchar日期转换的超出范围值

时间:2016-09-01 08:45:38

标签: sql-server tsql sql-server-2005 types date-conversion

我试图将我们系统中输入的日期作为YYYYMMDD格式的文本转换为日期。不幸的是,我们的系统允许使用任何月份的第31个月来表示它是一个重要的月份的最后一天,对于某些功能,如应计利息等。

我的日期显示为20160931,显然无法通过

转换
CONVERT(DATETIME, CONVERT(CHAR(8), [FIELD]))

并抛出超出范围的值错误。

我如何克服这个问题,以便将其转换为正确的值,在这种情况下30/09/2016

2 个答案:

答案 0 :(得分:2)

改编@ Shnugo的技术,我觉得最好让SQL决定月底。因此:

SELECT eomonth(CAST(y+m+'01' AS DATE))
FROM (VALUES(LEFT(@YourDate,4)
           ,SUBSTRING(@YourDate,5,2)
           ,SUBSTRING(@YourDate,7,2))) AS Parts(y,m,d)

将给予'2016-02-29'代替'2016-02-28',并为2月提供恒定的'28'。

答案 1 :(得分:1)

您可以尝试这样的事情:

DECLARE @YourDate VARCHAR(100)='20160231';

SELECT CAST(y+m+dNew AS DATE)
FROM (VALUES(LEFT(@YourDate,4)
           ,SUBSTRING(@YourDate,5,2)
           ,SUBSTRING(@YourDate,7,2))) AS Parts(y,m,d)
CROSS APPLY
(
    SELECT CASE WHEN CAST(m AS INT) IN(4,6,9,11) AND CAST(d AS INT)>30 THEN '30' 
           ELSE CASE WHEN CAST(m AS INT)=2 AND CAST(d AS INT)>28 THEN '28' ELSE d END 
           END AS dNew
) AS NewDay

2月29日你还有 - 另外 - 要检查年份是否除以4: - )

更新

现在我要发展@ Irawan的技术: - )

由于SQL Server 2005没有EOMONTH函数,但让SQL Server进行计算肯定会更好(2月29日隐式解决了!),我建议这样做:

DECLARE @YourDate VARCHAR(100)='20160231';

SELECT DATEADD(SECOND,-1,DATEADD(MONTH,1,CAST(y+m+'01' AS DATETIME)))
FROM (VALUES(LEFT(@YourDate,4)
           ,SUBSTRING(@YourDate,5,2)
           ,SUBSTRING(@YourDate,7,2))) AS Parts(y,m,d)

这将 - 无论如何 - 交付当月的最后一秒......

如果你想要一个普通的DATE(没有时间),你可以将SECOND更改为DAY,这将首先跳到第一天的午夜下一个月,而不是一天回来......

更新2使用现有日期(如果有效)

简单的语法......

DECLARE @YourDate VARCHAR(100)='20160229';

SELECT CASE WHEN ISDATE(@YourDate)=1 THEN @YourDate 
            ELSE DATEADD(SECOND,-1,DATEADD(MONTH,1,CAST(LEFT(@YourDate,4) + SUBSTRING(@YourDate,5,2) +'01' AS DATETIME)))
            END AS CorrectDate;