Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 为什么在过滤查询中使用过滤视图时无法转换?_Sql_Sql Server_Sql Server 2012 - Fatal编程技术网

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

Sql 为什么在过滤查询中使用过滤视图时无法转换?,sql,sql-server,sql-server-2012,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

下面是一个场景示例:

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值=1之前,将首先过滤坏数据

编辑:为了测试查询计划,我将转换改为TRY\u CONVERT。计划的结果仍然相同,并且看起来在转换之前进行了筛选:

我希望这两种方案都能奏效,因为视图已经过滤掉了坏数据

您使用的是view和view just stores定义。在运行时,您的查询将同时展开,此比较肯定会失败

 SELECT CONVERT(BIGINT,Value) Value
您可能还认为where子句应该过滤掉坏数据,但这可能会发生,也可能不会发生。Paul white在这里对此进行了解释:

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

还有一个问题,但正如您在对连接项的评论中看到的,存在不同的意见

另请参见下面的连接项示例,该示例与您的类似,它还依赖于过滤坏数据

 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
上述查询失败,错误如下

此查询失败,将varchar值“Gurka”转换为数据类型int时转换失败,尽管该行永远不会出现在输出中

来到你的编辑和下面的点

编辑:为了测试查询计划,我将转换改为TRY\u CONVERT。计划的结果仍然相同,并且看起来在转换之前进行了筛选:

您提供的计划是估计的,而不是实际的。请参阅以下答案,了解它们的不同之处:

另外,请查看Martin Smith的回答以了解更多示例


请参阅使用TRY\u CONVERT编辑到我的问题中的实际查询计划。在转换发生之前,应该先筛选出无效记录。实际上,我的查询计划是实际执行计划,您可以在筛选器上看到估计行与实际行。然而,我只是再次检查了这一点,我怀疑这可能是我正在使用的第三方探查器工具的问题,因为SSMS中的计划实际上显示了转换作为谓词的前半部分发生,而不是将谓词显示为仅检查“foo”。