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

Posted

技术标签:

【中文标题】尝试过滤转换后的日期时间值时超出范围的值【英文标题】:Out-of-range value when trying to filter on converted datetime value 【发布时间】:2017-10-17 16:07:00 【问题描述】:

我正在尝试从离岸开发人员导入文件中所有内容的临时表中提取某些日期的数据,因此我需要过滤掉“非数据”行并将剩余的字符串转换为日期时间。

这应该很简单,但是...我不断收到此错误:

将 varchar 数据类型转换为 datetime 数据类型导致值超出范围。

我已将查询拆开,确保没有剩余无效字符串,甚至尝试了几种不同的查询配置。这是我现在得到的:

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】:

我猜这是因为在您的 cmplt_date 字段中存在无效日期的值。是的,我知道您正在使用WHERE 子句过滤它们,但知道Logical Processing Order of the SELECT statement 并不总是实际顺序。这意味着,有时,SQL 引擎在完成过滤之前就开始执行您的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'

【讨论】:

以上是关于尝试过滤转换后的日期时间值时超出范围的值的主要内容,如果未能解决你的问题,请参考以下文章

ValueError:日期超出月份的范围

将 datetime2 数据类型转换为 datetime 数据类型导致值超出范围

将 varchar 数据类型转换为 datetime 数据类型导致 SQL 查询中的值超出范围

vue 过滤时间日期

从varchar数据类型到datetime数据类型的转换产生一个超出该范围的值

try_cast 和 cast 不同的结果。将日期数据类型转换为日期时间数据类型导致值超出范围