T-SQL:如何禁用整数运算的溢出检查?

时间:2018-03-01 21:26:44

标签: tsql int overflow integer-overflow integer-arithmetic

在C#中,我们有unchecked来禁用对整数运算的溢出检查

int int1;
unchecked
{
    int1 = 2147483647 + 10;
}

整数运算结果将换行到-2,147,483,639

但是在T-SQL中我找不到禁用边界检查的方法

DECLARE @INT1 INT
SET @INT1 = 2147483647 + 10

导致错误:

  

Msg 8115,Level 16,State 2,Line 2
  将表达式转换为数据类型int的算术溢出错误。

3 个答案:

答案 0 :(得分:0)

不是我认为这一定是一个好主意,但你可以把它包装在try / catch中。

declare @int int;

begin try
  set @int = 2147483647 + 10
end try
begin catch
  if ERROR_NUMBER() = 8115 
    set @int = 2147483647
  else 
    select
        ERROR_NUMBER() AS ErrorNumber  
       ,ERROR_MESSAGE() AS ErrorMessage;  
end catch 

select @int

结果:

2147483647

答案 1 :(得分:0)

根据Microsoft specification,由于INT数据类型的范围从-2,147,483,648到2,147,483,647,因此无法执行该操作(2147483647 + 10)。

相反,您可以使用BIGINT数据类型,如下所示:

DECLARE @number BIGINT;
SET @number = CAST(2147483647 AS BIGINT) + 10;
SELECT @number;
-- Output: 2147483657, as expected

答案 2 :(得分:0)

您可以将int值转换为bigint,执行添加,然后处理溢出,同时使用int表达式转换回case

declare @MaxInt as BigInt = Power( Cast( 2 as BigInt ), 31 ) - 1;
declare @Foo as Int = 2147483647;
declare @Bar as Int = 10;
declare @BigSum as BigInt;
set @BigSum = @Foo + Cast( 10 as BigInt );
select @MaxInt as MaxInt, @Foo as Foo, @Bar as Bar, @BigSum as BigSum,
  case when @BigSum <= @MaxInt then Cast( @BigSum as Int ) else
    Cast( @BigSum - Power( Cast( 2 as BigInt ), 32 ) as Int ) end as Unsigned;

更新:一个更整洁的示例,说明如何获取BigInt结果(来自先前的计算)并将其转换为Int而不会溢出:

declare @Samples as Table ( Value BigInt );
insert into @Samples ( Value ) values
  -- NB: At least one literal value needs to be cast as a BigInt to get BigInt values.  No, really.
  ( Cast( 0x0 as BigInt ) ), ( 0x1 ), ( 0x7FFFFFFF ), ( 0x80000000 ), ( 0x80000001 ), ( 0xFFFFFFFF ),
  ( -1 ), ( 0x4200000001 ), ( 0x7080000000 ); -- Some BigInt values beyond 32 bits.

select Value, Cast( Value as Binary(8) ) as ValueHex,
  Value & 0xFFFFFFFF as LSB32, Cast( Value & 0xFFFFFFFF as Binary(8) ) as LSB32Hex,
  Cast( case when Value & 0x80000000 = 0 then Value & 0xFFFFFFFF else
    ( Value & 0x7FFFFFFF ) - Cast( 0x80000000 as BigInt ) end as Int ) as IntResult
  from @Samples;

转换可以捆绑到UDF中,但性能可能会受到影响。