Sql server 理解为什么我对INT的转换不起作用

Sql server 理解为什么我对INT的转换不起作用,sql-server,tsql,sql-server-2012,Sql Server,Tsql,Sql Server 2012,我有一个非常简单的代码,我正试图运行,但由于我不理解的原因,它不起作用。这是我的密码: WITH CTE AS ( SELECT DISTINCT OrderNo FROM OrderDet WHERE PartNo LIKE '%.%' AND OrderNo NOT LIKE '%[a-z]%' ) SELECT * FROM CTE WHERE CAST(CTE.OrderNo AS INT) >= 21187 运行此代码会引发以下错误: 将v

我有一个非常简单的代码,我正试图运行,但由于我不理解的原因,它不起作用。这是我的密码:

WITH CTE AS
(
    SELECT DISTINCT OrderNo
    FROM OrderDet
    WHERE PartNo LIKE '%.%'
      AND OrderNo NOT LIKE '%[a-z]%'
)
SELECT * 
FROM CTE
WHERE CAST(CTE.OrderNo AS INT) >= 21187
运行此代码会引发以下错误:

将varchar值“20361E”转换为数据类型int时,转换失败

现在我知道OrderNo中没有包含“E”的值,但是,就我而言,我正在CTE中过滤掉它们。如果我自己在CTE中运行语句,我会得到580条记录,其中没有一条记录有任何字母


这是怎么回事?

如评论中所述,您无法真正控制是否在筛选之前尝试强制转换;这完全取决于SQLServer选择如何优化查询

此外,检查是否存在十进制和无a-z不是筛选非数字的非常可靠的方法

我认为,以下两种方法都消除了对CTE的需求,因为您只是使用它来强制过滤器首先发生。CTE可以折叠到查询的其余部分中

请尝试转换以下内容:

如果您使用的是不支持TRY\u CONVERT的旧版本,则可以尝试以下情况:

但是

由于现在我们知道了版本,您的查询可以简化为:

SELECT DISTINCT OrderNo
  FROM dbo.OrderDet
  WHERE PartNo LIKE '%.%'
    AND TRY_CONVERT(int, OrderNo) >= 21187;

正如评论中提到的,您无法真正控制是否在筛选之前尝试强制转换;这完全取决于SQLServer选择如何优化查询

此外,检查是否存在十进制和无a-z不是筛选非数字的非常可靠的方法

我认为,以下两种方法都消除了对CTE的需求,因为您只是使用它来强制过滤器首先发生。CTE可以折叠到查询的其余部分中

请尝试转换以下内容:

如果您使用的是不支持TRY\u CONVERT的旧版本,则可以尝试以下情况:

但是

由于现在我们知道了版本,您的查询可以简化为:

SELECT DISTINCT OrderNo
  FROM dbo.OrderDet
  WHERE PartNo LIKE '%.%'
    AND TRY_CONVERT(int, OrderNo) >= 21187;

欢迎来到SQL优化的辉煌世界。无法保证条件的实际计算顺序与您认为的逻辑计算顺序相匹配。更好的问题是,为什么您将字母数字值存储为OrderNo,然后尝试将其视为数字值。答案可能会提供一些线索。您使用的是哪个版本的SQL Server?如果它不是不受支持或非常接近,它应该有TRY_CONVERT,当它无法转换时会产生null而不是错误。SQL 2012是的,我知道TRY_CAST确实有效。然而,我觉得使用它就像绷带一样,而我最初的查询应该100%有效,我只是想解释一下原因。这看起来很奇怪,它没有像我想的那样工作。我将来到SQL优化的光辉世界。无法保证条件的实际计算顺序与您认为的逻辑计算顺序相匹配。更好的问题是,为什么您将字母数字值存储为OrderNo,然后尝试将其视为数字值。答案可能会提供一些线索。您使用的是哪个版本的SQL Server?如果它不是不受支持或非常接近,它应该有TRY_CONVERT,当它无法转换时会产生null而不是错误。SQL 2012是的,我知道TRY_CAST确实有效。然而,我觉得使用它就像绷带一样,而我最初的查询应该100%有效,我只是想解释一下原因。这看起来很奇怪,它没有像我想的那样工作。汉克斯,我没有意识到你不能真正控制是否在过滤器之前尝试强制转换。我认为100%的CTE将首先执行,第二个查询将只在CTE记录上执行。有点让我震惊的是,事实并非如此谢谢,我不知道你真的无法控制是否在过滤器前尝试施放。我认为100%的CTE将首先执行,第二个查询将只在CTE记录上执行。有点让我吃惊不是这样的
SELECT DISTINCT OrderNo
  FROM dbo.OrderDet
  WHERE PartNo LIKE '%.%'
    AND TRY_CONVERT(int, OrderNo) >= 21187;