在SQL Server中使用CAST()和子查询筛选记录

在SQL Server中使用CAST()和子查询筛选记录,sql,sql-server,tsql,casting,sql-server-2012,Sql,Sql Server,Tsql,Casting,Sql Server 2012,我遇到了这样一种情况:我需要将一个特定列强制转换为BIGINT,并检查该数字是否不大于X,但是,该列并不总是有数值 我尝试了以下方法,但它抛出了一个错误 DECLARE @RowType TABLE ( RowTypeID INT IDENTITY, RowType VARCHAR(10) ); INSERT @RowType VALUES('Numeric'); INSERT @RowType VALUE

我遇到了这样一种情况:我需要将一个特定列强制转换为BIGINT,并检查该数字是否不大于X,但是,该列并不总是有数值

我尝试了以下方法,但它抛出了一个错误

    DECLARE @RowType TABLE
      (
         RowTypeID INT IDENTITY,
         RowType   VARCHAR(10)
      );

    INSERT @RowType VALUES('Numeric');
    INSERT @RowType VALUES('NonNumeric');

    DECLARE @TempTable TABLE
      (
         ID        INT IDENTITY,
         RowTypeID INT,
         Value     VARCHAR(10)
      );

    INSERT @TempTable VALUES(1, '10');
    INSERT @TempTable VALUES(1, '20');
    INSERT @TempTable VALUES(2, '$10'); -- Non Numeric value

    -- This select throws error however ever I feel the behaviour 
    -- to be odd since the innser select should return only records of type 'NUMERIC'
    SELECT *
    FROM   (SELECT T.*
            FROM   @TempTable T
                   JOIN @RowType RT
                     ON RT.RowTypeID = T.RowTypeID
            WHERE  RT.RowType = 'Numeric') A -- With this sub query I expect only records of type 'NUMERIC' to be returned to the outer select
    WHERE  CAST(A.Value AS BIGINT) > 10

    -- Alternate approach which I can not use since 
    -- there are already lot of temp tables involved in procedure 
    --SELECT T.*
    --INTO   #Temp
    --FROM   @TempTable T
    --       JOIN @RowType RT
    --         ON RT.RowTypeID = T.RowTypeID
    --WHERE  RT.RowType = 'Numeric';

    --SELECT * 
    --FROM   #Temp
    --WHERE  CAST(Value AS BIGINT) > 10

    --DROP TABLE #Temp;

这是默认行为吗?还是我在这里遗漏了什么?

既然您在2012+上,我建议
尝试转换()
甚至
尝试转换()

try_convert(BIGINT,A.Value AS BIGINT) >  10
如果转换失败,将返回空值

这是默认行为吗

SQLSERVER可以自由地重新排列表达式,如果最终结果保持不变……您不应该依赖于预期的行为

下面是查询的计划

此处,在联接之前应用了一个.value,因此强制转换失败。下面的屏幕截图证实了这一点

伊兹克·本·甘在这里描述了这一点

下面是一些代码,它与您的代码有相同的问题,这也会因相同的问题而失败

WITH C AS
 (
SELECT name, datatype, val
FROM dbo.Properties
 WHERE datatype IN ('TINYINT', 'SMALLINT', 'INT', 'BIGINT')
)
SELECT *
 FROM C
WHERE CAST(val AS BIGINT) > 10;
下面是伊兹克的解释

从逻辑查询处理的角度来看,这样的代码不应该失败。但是,出于性能原因,SQL Server解析器在外部查询中取消内部查询代码的测试或内联,从而生成与不带表表达式的原始查询等效的代码。因此,代码失败并出现相同的错误

您可以使用
try cast/convert
来克服转换错误

下面是一个关于更多内部构件的好系列:

对于示例数据,您的意思是我应该这样添加:在哪里尝试转换(BIGINT,A.Value AS BIGINT)>10?如果是这样,我得到一个错误“关键字“AS”附近的语法不正确”。@RandomUser try_cast(A.Value为BIGINT)@RandomUser cast和convert的语法try_convert(type,Value)与try_cast(Value为type)不同