为什么过滤后的视图在过滤后的查询中使用时无法转换?

时间:2017-06-29 15:03:57

标签: sql sql-server sql-server-2012

以下是该方案的一个示例:

CREATE TABLE dbo.TestConversionTable
(
    Value VARCHAR(MAX)
)

INSERT INTO dbo.TestConversionTable VALUES ('1')
INSERT INTO dbo.TestConversionTable VALUES ('foo')

CREATE VIEW dbo.TestConversion 
AS
    SELECT CONVERT(BIGINT,Value) Value
    FROM dbo.TestConversionTable
    WHERE Value <> 'foo'
GO

SELECT * FROM dbo.TestConversion --this works
SELECT * FROM dbo.TestConversion WHERE Value = 1 --Error converting data type varchar to bigint.
SELECT * FROM dbo.TestConversion WHERE Value = '1' --Same thing, this doesn't work either.

我希望这两种方案都能正常工作,因为视图已经过滤掉了坏数据。更奇怪的是,第二个查询也不起作用。我只能在它们上面获取估计的执行计划(因为我实际上无法在没有错误的情况下运行查询),并且它们是相同的。根据估算的计划,在应用WHERE Value = 1之前,将首先过滤错误数据。

编辑:为了测试查询计划,我改为将CONVERT更改为TRY_CONVERT。计划的结果仍然相同,看起来过滤器发生在转换之前:

enter image description here

1 个答案:

答案 0 :(得分:1)

  

我希望这两种方案都能正常工作,因为视图已经过滤掉了不良数据

您正在使用视图并仅查看商店定义。在运行时,您的查询将被扩展,此比较肯定会失败

 SELECT CONVERT(BIGINT,Value) Value

您可能还会想,where子句应该过滤掉不良数据,但这可能会也可能不会发生...... Paul在此解释过: TSQL divide by zero encountered despite no columns containing 0

  

SQL是一种声明性语言;您编写的逻辑描述所需结果的查询,但优化程序可以生成物理计划。此物理计划可能与查询的书面形式无关,因为优化程序不会简单地重新排序&#39;步骤&#39;从查询的文本形式派生出来,它可以应用300多种不同的转换来找到有效的执行策略。

还有一个connect item raised,但您在连接项的评论中看到了不同的意见

另见下面的连接项示例,与您的相似,也依赖于过滤掉不良数据

 create table albert(a int NOT NULL,
                        b varchar(23) NOT NULL)
   create table stina (a int NOT NULL)  
  go
   insert albert (a, b) 
       values  (1, '99'), 
              (2, 'Gurka'),
              (3, '89')
   insert stina (a) values(1), (3), (9), (12)
   go
   SELECT a.a, a.b + 100   
   FROM   albert a
   JOIN   stina s ON s.a = a.a

上述查询失败并出现以下错误

  

此查询失败,&#34;转换varchar值时转换失败&#39; Gurka&#39;数据类型为int。&#34;,尽管此行永远不会出现在输出

来到您的编辑及以下点

  

编辑:为了测试查询计划,我改为将CONVERT更改为TRY_CONVERT。计划的结果仍然相同,看起来过滤器发生在转换之前:

您提供的计划是估计的而不是实际计划。请参阅以下答案:Differences between estimated and actual execution plans

另请参阅Martin Smith的答案以获取更多示例

https://stackoverflow.com/a/7192951/2975396