尝试过滤转换后的日期时间值时超出范围的值

时间:2017-10-17 16:07:00

标签: tsql sql-server-2012

我试图从临时表中提取某些日期的数据,而临时开发人员导入了文件中的所有内容,因此我需要过滤掉非数据"行并将剩余的字符串转换为datetime。

哪个应该足够简单但是...我一直收到这个错误:

将varchar数据类型转换为日期时间数据类型会导致超出范围的值。

我已经接受了查询并将其拆开,确保没有无效的字符串,甚至尝试了一些不同的查询配置。这就是我现在所拥有的:

SELECT *
FROM 
(
    select cdt = CAST(cmplt_date as DateTime), *
    from stage_hist

    WHERE cmplt_date NOT LIKE '(%'
    AND ltrim(rtrim(cmplt_date)) NOT LIKE ''
    AND cmplt_date NOT LIKE '--%'
) f
WHERE f.cdt BETWEEN '2017-09-01' AND '2017-10-01'

为了确保转换至少有效,我可以运行内部查询,并且转换实际上适用于所有行。我获得了行的有效数据集而没有错误,因此实际的转换工作正常。

BETWEEN语句必须抛出错误,对吗?但是我已经成功地使用了两个字符串,甚至从表中获取了一个值并使用它进行了测试查询,这也成功地运行了:

select 1
WHERE CAST('      2017-09-26' as DateTime) BETWEEN '2017-09-01' AND '2017-10-01'

因此,如果所有演员都是单独工作的,那么在运行真实查询时我怎么会出现超出范围的错误?

1 个答案:

答案 0 :(得分:1)

我猜这是因为在cmplt_date字段中存在的值不是有效日期。是的,我知道您使用WHERE子句过滤它们,但知道Logical Processing Order of the SELECT statement并不总是实际的顺序。这意味着有时候SQL Engine会在完成过滤之前开始执行CAST操作。

您使用的是SQL Server 2012,因此您只需添加TRY_CAST

即可
SELECT *
FROM 
(
    select cdt = TRY_CAST(cmplt_date as DateTime), *
    from stage_hist

    WHERE cmplt_date NOT LIKE '(%'
    AND ltrim(rtrim(cmplt_date)) NOT LIKE ''
    AND cmplt_date NOT LIKE '--%'
) f
WHERE f.cdt BETWEEN '2017-09-01' AND '2017-10-01'