3

我的问题似乎很简单,但我被困在这里。我有一个表,其中有一个名为“SrcID”的“nvarchar”列,我在其中存储了数字和字符串。现在,当我尝试在“加入”条件下检查该列上的“IsNumeric”时,如下所示,

   ISNUMERIC(SrcID) = 1 AND SrcID > 15

我收到以下错误:

  Msg 245, Level 16, State 1, Line 47
  Conversion failed when converting the nvarchar value 'Test' to data type int.

令人惊讶的是,当我删除检查“SrcID > 15”时,我的查询运行正常。我应该在此声明中包含其他内容吗?

请帮助我解决问题。提前致谢!!

4

2 回答 2

4

您不能指望数据库评估过滤表达式的顺序。有一个查询优化器会评估您的 SQL 并根据它认为会产生最佳性能的内容构建一个执行查询的计划。

在这种情况下,IsNumeric()不能与索引一起使用,这意味着对表中的每一行运行一个函数。因此,它几乎永远不会提供最佳感知性能。将此与SrcID > 15表达式进行比较,该表达式可以与索引匹配(如果存在),并且即使不匹配也只是单个运算符表达式。它还可用于过滤IsNumeric()函数需要运行的潜在行数。

您可以通过视图、子查询、CTE、CASE 语句或计算列来解决这个问题。这是一个 CTE 示例:

With NumericOnly As 
(
    SELECT <columns> FROM MyTable WHERE IsNumeric(SrcID) = 1
)
SELECT <columns> FROM NumericOnly WHERE SrcID > 15

这是一个 CASE 语句选项:

SELECT <columns> FROM MyTable WHERE CASE WHEN IsNumeric(SrcIC) = 1 THEN Cast(SrcID As Int) ELSE 0 END > 15
于 2012-01-17T15:01:44.937 回答
3

子句中的过滤器WHERE不按任何特定顺序进行评估。

这是 SQL Server 的一个常见误解 - 优化器将检查它认为最快/最简单的任何条件,并尝试以最有效的方式限制数据。

在您的示例中,您可能在 上有一个索引SrcID,并且优化器认为首先将结果限制在 的位置会更快SrcID > 15,然后在所有这些行上运行该函数(因为该函数将需要检查每一行)。

您可以尝试使用括号强制执行操作顺序,例如:

WHERE (ISNUMERIC(SrcID) = 1) AND SrcID > 15

或使用案例陈述:

WHERE CASE WHEN ISNUMERIC(SrcID) = 1 THEN SrcID > 15 ELSE 1=0 END

于 2012-01-17T15:01:27.763 回答