首先,以下是有关我的环境的一些信息:
我正在SQL 2014实例上运行SQL 2005数据库。 COLLATION是SQL_Latin1_General_CP1_CI_AS。以下是我的DBCC USEROPTIONS的结果
这是我的问题。
我继续遇到以下2个错误,具体取决于我何时尝试从视图中选择,并且针对DATETIME或DATETIME2类型的转换列使用WHERE子句。
(DATETIME2) Msg 241,Level 16,State 1,Line 122 从字符串转换日期和/或时间时转换失败。
和...
(DATETIME) Msg 242,Level 16,State 3,Line 122 将varchar数据类型转换为日期时间数据类型会导致超出范围的值。
我的问题SOUNDS看似简单,就像我必须是一个mook并且要么在WHERE中传递格式不正确的值,要么不考虑语言设置,排序规则和优化器优先级。
所以这是我的问题。
DECLARE @DATEVALUE DATETIME = '01-05-2015 14:23:05'
SELECT t.* FROM Reports.MyReportView WHERE t.MyDateColumn = @DATEVALUE
无论我尝试什么,这都是错误的。
将字符串转换为DATETIME并没有问题。 像...
SELECT CAST('03/28/2011 18:03:40' AS DATETIME)
工作得很好。
问题似乎只发生在我的WHERE子句中。我看了很多建议,试过很多东西,比如将语言设置改为英国或法国,将DATEFORMAT改为ymd,dmy,mdy,尝试了一些我发现的其他解决方案......
DECLARE @F7 nvarchar(10) = '01/05/2015'
DECLARE @F8 nvarchar(10) = '00:00:00'
DECLARE @NEWTIME DATETIME
DECLARE @Date VARCHAR(20)
SET @Date = RIGHT(@F7,4)+'/'+SUBSTRING(@F7,4,2)+'/'+LEFT(@F7,2)
DECLARE @time DATETIME
SET @time = CONVERT(DATETIME, @Date + ' ' + @F8)
......是的,那就输出DATETIME就好了。但是当我尝试在WHERE子句中使用该值时... KAAAABOOOOOOOM !!!所以我没有解决这个问题的运气。
我能想到的唯一一件事就是优化器正在打扰我,因为它正在重新安排幕后的查询,并且我将VALID日期时间变量与无效的VARCHAR字符串进行比较。当我在查询顺序中转换字符串时,因此View实际上导致了失败,并且与SQL Server的日期时间转换无关。
请帮忙。
更新
好的。我按照每个人的建议,将View中的日期转换重写为SubQuery / SubView,然后加入它。以下是新转换代码的内容......
CONVERT(DATETIME,
CASE
WHEN
(
CASE
WHEN REPLACE(ISNULL(t.DayCol,''),' ','') = ''
THEN NULL ELSE REPLACE(ISNULL(t.DayCol,''),' ','') END
) IS NULL
OR
(
CASE WHEN REPLACE(ISNULL(t.MonthCol,''),' ','') = ''
THEN NULL ELSE REPLACE(ISNULL(t.MonthCol,''),' ','') END
) IS NULL
OR
(
CASE WHEN REPLACE(ISNULL(t.YearCol,''),' ','') = ''
OR t.YearCol = 'NoSelection'
THEN NULL ELSE t.YearCol END
) IS NULL
OR
ISDATE
(
CONCAT
(
RIGHT('0' +REPLACE(MonthCol,' ',''),2),'/',
RIGHT('0' + REPLACE(t.DayCol,' ',''), 2),'/',
REPLACE(YearCol,' ','')
)
) = 0
THEN NULL
ELSE
CONCAT
(
RIGHT('0' +REPLACE(MonthCol,' ',''),2),'/',
RIGHT('0' + REPLACE(t.MonthCol,' ',''), 2),'/',
REPLACE(YearCol,' ','')
)
END) as 'MyDateColumn'
这是令人尴尬的代码,但它起作用,解决了问题并且不幸的是必要,因为有人不想将日期值存储为古怪的数据库结构中的日期列...所以它可能会帮助遇到此问题的人问题
答案 0 :(得分:1)
如果您要转换的数据列可能包含空值或者可能包含无效的日期数据,那么您将收到此错误。在过滤WHERE子句上的数据之前,SQL引擎将尝试对所有潜在数据执行CAST。你需要做的是做一个子查询,然后选择并反对:
SELECT CAST(a.StringField AS datetime) AS TheDate
FROM (
SELECT a.* FROM MyTable WHERE StringField = '12/1/2014'
) a
OR:
SELECT CAST(a.StringField AS datetime) AS TheDate
FROM (
SELECT a.* FROM MyTable WHERE ISDATE(StringField) = 1
) a
WHERE CAST(a.StringField as datetime) = '12/1/2014'