View Alias上的WHERE导致错误

Bob*_*orn 5 t-sql sql-server

我有这样的观点:

SELECT location, CAST(SUBSTRING(location, 9, 4) AS int) AS ProcessCode
FROM   dbo.asset
WHERE  (status NOT IN ('INACTIVE', 'NOT READY', 'LIMITEDUSE'))
AND (location LIKE '[1-6]-[12]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]-_')
Run Code Online (Sandbox Code Playgroud)

如果我这样称它,它的工作原理是:

SELECT * FROM FooView
Run Code Online (Sandbox Code Playgroud)

但是,如果我添加一个WHERE子句:

SELECT * FROM FooView WHERE ProcessCode > 0
Run Code Online (Sandbox Code Playgroud)

我收到此错误:

将varchar值'-01-'转换为数据类型int时转换失败.

为什么?由于位置必须采用格式1-2-100-0800-A,因此我不知道如何存在转换错误.是否有可能CASTWHERE有机会过滤结果之前失败?如果是这样,为什么第一个查询有效?

编辑 - 工作 - 周围

我只是让一位同事建议一个好的解决方案.它有效,但它仍然无法解释为什么最初的问题.

这是在SELECT for ProcessCode中:

CASE WHEN location LIKE '[1-6]-[12]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]-_'
THEN CAST(SUBSTRING(location, 9, 4) AS int) ELSE 0 END AS ProcessCode, 
Run Code Online (Sandbox Code Playgroud)

Ric*_*iwi 4

改变你的看法

SELECT location,
       CASE WHEN SUBSTRING(location, 9, 4) > ''
             AND SUBSTRING(location, 9, 4) NOT LIKE '%[^0-9]%' THEN
                 CAST(SUBSTRING(location, 9, 4) AS int) END AS ProcessCode
  FROM dbo.asset
 WHERE (status NOT IN ('INACTIVE', 'NOT READY', 'LIMITEDUSE'))
   AND (location LIKE '[1-6]-[12]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]-_')
Run Code Online (Sandbox Code Playgroud)

查看此连接项目

SQL Server 可以按照它决定的优化顺序自由地评估 WHERE/SELECT 子句。除非具体化为 INDEXED VIEW,否则视图会扩展到外部查询,因此您的 WHERE 子句实际上正在简化到视图中,即

SELECT * FROM FooView WHERE ProcessCode > 0
 -- is really seen as
SELECT location, CAST(SUBSTRING(location, 9, 4) AS int) AS ProcessCode
FROM   dbo.asset
WHERE  (status NOT IN ('INACTIVE', 'NOT READY', 'LIMITEDUSE'))
AND (location LIKE '[1-6]-[12]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]-_')
AND CAST(SUBSTRING(location, 9, 4) AS int) > 0 ---- << Expanded inline
Run Code Online (Sandbox Code Playgroud)

由于该表达式同时用于 SELECT 和 WHERE 子句,因此 SQL Server 似乎决定在原始检索中首先解析 SELECT 子句中的表达式。通过使用 Ctrl-L 查看查询执行计划可以轻松看出这一点。您将看到 SQL Server 从表中进行一次检索,同时采用 2 个表达式 beinglocation和。CAST(SUBSTRING(location, 9, 4) AS int)