你可以试试这样的:
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;