【问题标题】:IsNumeric in SQL Server JOINSQL Server JOIN 中的 IsNumeric
【发布时间】:2012-02-12 09:08:41
【问题描述】:

我的问题似乎很简单,但我被困在这里。我有一个表,其中有一个名为“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”时,我的查询运行正常。我应该在此声明中包含其他内容吗?

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

【问题讨论】:

    标签: sql-server-2008 isnumeric


    【解决方案1】:

    您不能指望数据库评估过滤表达式的顺序。有一个查询优化器会评估您的 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
    

    【讨论】:

    • CTE 应该也可以工作,如果你是 2008 年的标签 - 你可能需要在 WITH 之前添加一个分号:;WITH Numericonly AS...
    • 我使用的是 2012,CTE 选项也不适合我。
    【解决方案2】:

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

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

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

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

    WHERE (ISNUMERIC(SrcID) = 1) AND SrcID &gt; 15

    或者用case语句:

    WHERE CASE WHEN ISNUMERIC(SrcID) = 1 THEN SrcID &gt; 15 ELSE 1=0 END

    【讨论】:

    • 第一个不起作用(刚刚在 SQL Server 2008 上测试过),第二个像魅力一样工作。编辑。- 抱歉,此评论是针对另一个答案的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-01
    • 2010-09-29
    相关资源
    最近更新 更多