Tsql T-sql—将nvarchar数据类型转换为datetime数据类型会导致值超出范围。=和LIKE之间的差异

Tsql T-sql—将nvarchar数据类型转换为datetime数据类型会导致值超出范围。=和LIKE之间的差异,tsql,sql-like,Tsql,Sql Like,我对以下WHERE子句有疑问 WHERE I.new_outstandingamount = 70 AND ISNUMERIC(SUBSTRING(RA.new_stampernumber,7, 4)) = 1 AND (DATEDIFF(M,T.new_commencementdate, SUBSTRING(RA.new_stampernumber,7, 10)) >= 1) AND RA.new_applicationstatusname = 'Comp

我对以下WHERE子句有疑问

WHERE
    I.new_outstandingamount = 70
    AND ISNUMERIC(SUBSTRING(RA.new_stampernumber,7, 4)) = 1
    AND (DATEDIFF(M,T.new_commencementdate, SUBSTRING(RA.new_stampernumber,7, 10)) >= 1)
    AND RA.new_applicationstatusname = 'Complete'
    AND I.new_feereceived > 0
    AND RA.new_stampernumber IS NOT NULL
    AND T.new_commencementdate IS NOT NULL
RA.new_stampernumber是一个字符串值,其中包含三条长度相同的串联信息。此字符串中的中间信息是格式为yyyy-MM-dd的日期

为了筛选出该字符串中日期未按预期格式化的任何行,我使用ISNUMERIC函数检查前4个字符是否为数字

当我运行查询时,会收到一条错误消息

The conversion of a nvarchar data type to a datetime data type resulted in an out-of-range value.
导致此错误发生的行是

AND (DATEDIFF(M,T.new_commencementdate, SUBSTRING(RA.new_stampernumber,7, 10)) >= 1)
当我注释掉这一行时,我没有得到一个错误

奇怪的是,如果我替换

AND ISNUMERIC(SUBSTRING(RA.new_stampernumber,7, 4)) = 1

查询成功运行

更奇怪的是,如果我把上面的工作线换成这个

AND SUBSTRING(RA.new_stampernumber,11, 1) = '-'
我再次收到错误消息。但如果我用类似的比较替换等号,它会起作用:

AND SUBSTRING(RA.new_stampernumber,11, 1) LIKE '-'
当我删除DATEDIFF函数并比较每个查询的结果时,它们都返回相同的resultset,因此这不是由不同子句返回的不同数据造成的

如果每个子句返回的数据实际上是相同的,有谁能向我解释是什么导致某些子句抛出超出范围的错误,而不是其他子句抛出超出范围的错误

谢谢,
尼尔

不同的执行计划

不能保证
WHERE
子句是按特定顺序处理的。大概当它工作时,它会在尝试转换之前过滤掉出错的行

另外,
ISNUMERIC
本身对于您想要的东西不是很可靠。我将
DATEDIFF
表达式更改为如下所示

DATEDIFF(M, T.new_commencementdate, 
                    CASE
                    WHEN RA.new_stampernumber LIKE 
                    '______[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]%' 
                     THEN SUBSTRING(RA.new_stampernumber, 7, 10)
                     END) >= 1 ) 

我使用ISDATE()函数简化了这个过程
DATEDIFF(M, T.new_commencementdate, 
                    CASE
                    WHEN RA.new_stampernumber LIKE 
                    '______[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]%' 
                     THEN SUBSTRING(RA.new_stampernumber, 7, 10)
                     END) >= 1 )