为什么在某些情况下错误消息SQL转换失败(日期),而在其他情况下却没有?

时间:2018-09-20 14:05:12

标签: sql sql-server tsql

我在SQL查询中遇到一个非常奇怪的问题,我收到一条错误消息“从字符串转换日期和/或时间时转换失败。”出乎意料的是(我没想到),但是对查询进行了不同的处理,但有一些工作却没有。因此,我有一个可行的解决方案,但我想了解为什么有些路径无效而有些路径无效。

背景:myTable是具有myDateAsString的表,该表以dd / mm / yyyy格式将日期保存为字符串。无论如何,我无法更改此设置或更改数据库结构,但希望将一些数据作为日期进行处理。

初始数据提取:此方法有效(但没有所需的WHERE子句来缩小数据范围(我希望如果有无法转换的数据会在此处引发错误)

SELECT CONVERT(date, myDateAsString, 103) as myDate
FROM   myTable

WHERE子句的添加:我只想提取“将来”的数据。由于上面的查询可以正常工作,所以我希望它也能正常工作,但是会引发错误“从字符串转换日期和/或时间时转换失败。”

SELECT *
FROM (
     SELECT CONVERT(date, myDateAsString, 103) as myDate
     FROM   myTable) as ConvertedData
WHERE myDate > GETDATE()

是否有失败的原因?数据看起来都是正确的日期(尤其是上面的“初始数据提取”查询不会失败。

对于通用表表达式:基于执行顺序等,上述内容似乎(从搜索中发现)可能会失败...因此,我认为CTE有所帮助,并尝试了以下操作

WITH ConvertedData_CTE (myDate)
AS
(
   SELECT CONVERT(date, myDateAsString, 103) as myDate
   FROM   myTable
)

SELECT *
FROM   ConvertedData_CTE
WHERE myDate > GETDATE()

再次显示错误消息“从字符串转换日期和/或时间时转换失败。” (注意:如果我删除WHERE子句,则不会显示错误消息)

再尝试一次:因此我尝试使用这样的表变量

DECLARE @ConvertedData TABLE (myDate date)

INSERT INTO @CovertedData (myDate)
SELECT CONVERT(date, myDateAsString, 103) as myDate
FROM   myTable

SELECT *
FROM   @ConvertedDate
WHERE  myDate > GETDATE()

令我惊讶的是,它奏效了。

所以我的问题是为什么最后一个查询有效,但是CTE和内部选择无效?在我看来,这有点反常理,因为我希望它们都能正常工作,但是想更好地理解为什么有些有用,有些却没有。

编辑:添加样本数据

样本数据

  

2013年8月22日   2012年10月3日   2013年8月22日   2013年8月24日   2013年8月27日   2013年8月21日   2013年8月23日   15/03/2013   2010/07/04   2013年8月22日   '/ /'

注意:原始表中的数据有3394行,如果我选择前1010行,则可以使所有查询生效;此数据表示行1010到1020,如果我限制原始表的行,则按描述的方式工作...但是,如果我仅使用此数据创建新表...,则查询全部正常 (这对我来说很有意义,因为这就是查询中正在发生的事情;即新表,表变量有效,但其他方法无效) 希望能指出某种正确的方向

编辑:其他信息,最初为了清楚起见没有提供 上面的查询在它们上面都有一个附加的WHERE子句,因为数据库中的某些数据(应该清楚地存储为NULL)存储为'/ /' 因此,在上述所有查询中都有一个附加的WHERE myDateAsString <>'/ /' 注意:我已经将示例数据更新为也包含该数据项,奇怪的是查询仍然可以工作(只有一个“坏数据点”和其中的<>子句可以排除)...问题仍然是为什么排除可以工作在SELECT上发生转换,但是在转换完成后在哪里使用GETDATE()在WHERE上出错?

1 个答案:

答案 0 :(得分:1)

我的猜测是您的某些文本日期数据已损坏,或者格式无法转换为日期。要清除此类记录,您可以尝试使用TRY_CONVERT

SELECT *
FROM myTable
WHERE TRY_CONVERT(DATETIME, myDateAsString) IS NULL;

一旦发现麻烦的行,则应修复数据,将列转换为日期类型,然后停止将日期信息存储为纯文本。