我需要一个表达式,只有在匹配VARCHAR
,DATETIME
,{{1}时才会将文本(dd/MM/yyyy
)列转换为d/MM/yyyy
}或dd/M/yyyy
。如果它不匹配,那么我想要一个d/M/yyyy
。
我有这个......
NULL
然而,例如CASE ISDATE([DateField])
WHEN 1 THEN CONVERT(DATETIME,[DateField],103)
ELSE NULL
END
失败了 - 使用“从字符串转换日期时转换失败”错误 - 而我希望它返回'15/04/76'
示例输出
NULL
有没有办法迫使'1/6/1976' -> 1976-06-01
'01/06/1976' -> 1976-06-01
'13/06/2001' -> 2001-06-13
'06/13/2001' -> NULL
'13/06/76' -> NULL
验证给定的格式?
The documentation似乎暗示......
ISDATE仅在与CONVERT函数一起使用时才是确定性的 指定了CONVERT样式参数,样式不等于0,100, 9,或109。
但是ISDATE
只接受一个参数,那么如果我不这样做,我如何“将它与CONVERT函数一起使用”?
答案 0 :(得分:1)
你可以在这里做一个嵌套的case语句。第一个可以检查你是否有一个10个字符串2 for day,2个月,4个for year和2个分隔符= 10个字符。
SET DATEFORMAT DMY;
Case When DateField Like '%/%/[0-9][0-9][0-9][0-9]'
Then Case When IsDate(DateField) = 1
Then CONVERT(DATETIME,[DateField],103)
End
End
修订:我更改了代码以使用类似搜索,强制在字符串末尾有一个/ YYYY,然后执行IsDate检查以允许一天和/或一个月。
答案 1 :(得分:1)
嗯,首先,为什么你要将日期时间值存储在varchar列中呢?由于各种原因,这是一个重要的罪,其中最重要的是,您无法验证数据是否(或可转换为)日期时间。您还应该考虑验证输入,即使您将列保留为varchar,因此您没有想要认为有效的各种各样的潜在格式。
所以这是一种方式,借用@G Mastros:
DECLARE @f TABLE(i INT, d VARCHAR(32));
INSERT @f VALUES
(1,'15/04/76'),
(2,'15/04/1976'),
(3,'1/3/1976'),
(4,'1/3/76'),
(5,'15/3/1976'),
(6,'22/22/22'),
(7,'Yesterday');
SET DATEFORMAT DMY;
SELECT i, d, d2 = CASE WHEN ISDATE(d) = 1
AND d LIKE '%/[0-9][0-9][0-9][0-9]'
THEN CONVERT(DATETIME, d, 103) END
FROM @f;
结果:
i d d2
- ---------- -----------------------
1 15/04/76 NULL
2 15/04/1976 1976-04-15 00:00:00.000
3 1/3/1976 1976-03-01 00:00:00.000
4 1/3/76 NULL
5 15/3/1976 1976-03-15 00:00:00.000
6 22/22/22 NULL
7 Yesterday NULL
PS这将是SQL Server 2012中TRY_CONVERT
的一个很好的例子。它正是你所要求的 - 它试图转换为指定的数据类型;如果不能,则返回NULL
。
答案 2 :(得分:0)
感谢回复人员。
我这样做了......
CASE ISDATE([DateField]) WHEN 1 THEN
CASE WHEN SUBSTRING([DateField],LEN([DateField])-4,1) = '/' THEN
CASE WHEN CHARINDEX('/',[DateField],LEN([DateField])-3)=0 THEN
CONVERT(datetime, [DateField] , 103)
END
END
END
这是非常讨厌的事情,所以仍然会喜欢更整洁的东西!
但这也不起作用 - 它仍然是mm / dd / yyyy格式日期的错误!
废弃最后一条评论 - 它现在似乎有效吗?可能与SET DATEFORMAT