在SQL Server中使用CAST()和子查询筛选记录
我遇到了这样一种情况:我需要将一个特定列强制转换为BIGINT,并检查该数字是否不大于X,但是,该列并不总是有数值 我尝试了以下方法,但它抛出了一个错误在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
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)不同