嵌套选择中的强制转换顺序

时间:2014-07-23 09:31:32

标签: sql-server

我面临一个奇怪的问题。我要查询,应该给出相同的结果(所有FieldX都是文本类型):

SELECT CAST(CAST(myfield as varchar(max)) AS smallint)
  FROM (SELECT [Field1] AS myfield
          FROM [iPad-CC].[dbo].[ZZZ_IMP_TEMP]
         WHERE [Field0] IS NULL) as base
 WHERE myfield IS NOT NULL

SELECT myfield
 FROM (SELECT CAST(CAST([Field1] as varchar(max)) AS smallint) AS myfield
        FROM [iPad-CC].[dbo].[ZZZ_IMP_TEMP]
       WHERE [Field0] IS NULL) as base
 WHERE myfield IS NOT NULL

虽然第一次工作正常,但第二次抛出245错误(无法将varchar类型'dummy'转换为smallint)。 好吧,'dummy'是连续的,其中Field0不为null,所以似乎CAST发生在每一行而不管WHERE子句(查询优化器非常聪明......),并且错误是有意义的。 没有意义的是为什么,如果我删除最后一个WHERE子句,一切都没有错误(但不幸的是我也得到了不需要的行):

SELECT myfield
 FROM (SELECT CAST(CAST([Field1] as varchar(max)) AS smallint) AS myfield
        FROM [iPad-CC].[dbo].[ZZZ_IMP_TEMP]
       WHERE [Field0] IS NULL) as base

当然这是一小块复杂的存储过程,使用第一个查询会导致更多代码(因为内部SELECT是各种动态查询中使用的变量)。

2 个答案:

答案 0 :(得分:0)

请尝试以下代码:

和Field1不是空

SELECT CAST(CAST([Field1] as varchar(max)) AS smallint) AS myfield
FROM [iPad-CC].[dbo].[ZZZ_IMP_TEMP]
WHERE [Field0] IS NULL
    AND Field1 IS NOT NULL

答案 1 :(得分:0)

这是因为查询优化器尝试在最里面的子查询中应用条件(在您的情况下为myfield IS NOT NULL)。

这实际上对性能有很大帮助,但在这种情况下,会破坏查询,因为它会尝试CAST该值,并检查您期望不会出现的值的条件-query。

更新:

您可以假设您的原始查询已转换为此查询:

SELECT myfield
FROM (SELECT CAST(CAST([Field1] as varchar(max)) AS smallint) AS myfield
     FROM [iPad-CC].[dbo].[ZZZ_IMP_TEMP]
     WHERE [Field0] IS NULL AND 
     CAST(CAST([Field1] as varchar(max)) AS smallint)IS NOT NULL) as base